<?php
# level=1
# 不需要每次请求都循环500多次
    @RequestHeader(value = "channel") String channel, 
    @RequestHeader(value = "mobileModel") String mobileModel,
    @RequestHeader(value = "osVersionCode") String osVersionCode,
    @RequestHeader(value = "appVersionCode") String appVersionCode,
    @RequestHeader(value = "appVersionName") String appVersionName,
    @RequestHeader(value = "mobileType") String mobileType,
    @RequestHeader(value = "deviceToken") String deviceToken,
    @RequestHeader(value = "userId") String userId,
    @RequestHeader(value = "userType") String userType, String token, String callback)


  #  先检测是否已存在用户，存在则userId制空
  #  查询是否存在设备，存在则修改设备的一些信息，否则新增设备


    getShareTemplateList

    getShareTemplateList(String token, String callback)

    医生模板
    type in (1001,1002,1003,1004,1005,1006,1007)
    病人模板
    type in (2001,2002,2003)


                @RequestMapping(value = "shareSuccess", method = RequestMethod.POST)
    shareSuccess(String token, String callback, String type, Long targetId)




    1，判断token是否是医生
    2，参数不能为空且type只能为1003
    3，CreditLogService->add
        1,验证医生是否已经审核
        2，医生不能为空
        3，返回boolean = 如果医生等级等于一，当前时间大于会员生效时间，且当前时间小于会员结束时间，或者会员结束时间为空
        4，医生关联病例表信息    t_customer_ext_hospital 如果查询的值不等于空，
        返回的boolean = 医生等级等于一，病例更新时间大于会员开始时间，病例更新时间小于会员结束时间，或者会员结束时间为空
        5，查询医术值规则，医术值规则不能为空 t_credit_ext_rule
        6，如果第5步 all_limit限制次数大于0 单日限制次数
        查询log表里的记录对比总条数是否等于限制次数，等于就return   t_credit_log
        7，如果类型为4=分配方案，5=自建方案升级到官方方案，如果有 targetId 搜索条件带上 targetId
        8，如果是分配病人并且有其他医生已经给该病人分配过方案医数值加1 t_credit_log
        9，如果该医生已给病人分配方案添加医数值直接return  t_credit_log
        10，如果总限制次数等于0 或者 所以记录次数小于总限制次数 添加一条日志记录  t_credit_log  更新医生的医术值  t_doctor_basic


            @RequestMapping(value = "sendInnerShare", method = RequestMethod.POST)
    sendInnerShare(String token, String callback, String targetType, Long targetId, String toCustomerIds,
                   Long extHospitalId, Long linkPointId, Long pointId)


1，判断是否是医生
2，targetType 包含1=须知，2=量表，3=医术值发布
3，targetType 包含1，2  targetId,linkPointId,toCustomerIds有一个值不能为空
4，targetType 包含3且targetId<=0 或者 toCustomerIds为空 直接 return
5，通过传参的extHospitalId查询病例记录  t_customer_ext_hospital
6，判断type类型，循环病例ID
  1，如果是须知
    1，查看有没有这个病人   t_customer_basic
    2，通过传参 linkPointId 查看须知关联表有没有记录 t_follow_point_link
    3, MsgPushFacade->pushCustomerPointNoteMsg （医生详情，病人详情，须知关联详情，病例详情）
      1，判断是医生推荐须知，还是医生提醒查看须知 status 1 别人的须知，查看 2 自己的须知，提醒
      2，病例不为空，且病例customerId=病人Id，通过病例模板ID查询模板记录里面的refTemplateId如果不为空且reftemplateId=须知关联表templateId说明是须知提醒。
    4，第三步调用 MsgPushFacade->pushCustomerPointNoteMsg1 (医生信息，病人信息，须知关联信息，病例信息，抬头，状态)
      1，添加msg记录  t_msg_basic
      2，添加百度推送
      3, 微信推送消息，并增加一条记录 t_wx_template_msg_ext_customer
      4，如果上一步发送失败，发送备用的模板消息
  2，如果是量表
    1，查看有没有这个病人   t_customer_basic
    2，通过传参 linkPointId 查看须知关联表有没有记录 t_follow_point_link 
    3, MsgPushFacade->pushCustomerFollowPointSurveyMsg （医生详情，病人详情，须知关联详情，病例详情）
      1，MsgPushFacade->pushCustomerFollowPointSurveyMsg1 （医生详情，病人详情，须知关联详情，病例详情，医生名称）
      2，添加msg记录  t_msg_basic
      3，添加百度推送
      4，如果换做操作ID不为空，查询模板节点记录 t_follow_template_point
      5，推送微信消息 WechatTemplateSendService->pushTextToWXCustomerWithDoctor
        1, 微信推送消息，并增加一条记录 t_wx_template_msg_ext_customer
        2，如果上一步发送失败，发送备用的模板消息
  3，如果是医术发布
    1，查看有没有这个病人   t_customer_basic
    2，通过targetId = id 查询 医数发布表记录 t_publish_basic
    3，MsgPushFacade->pushIfuPublishCustomerMsg (医生信息, 患者信息, 医数信息) 
    4，发送推送信息 WechatTemplateSendService->pushTextToWXCustomerWithDoctor
        1, 微信推送消息，并增加一条记录 t_wx_template_msg_ext_customer
        2，如果上一步发送失败，发送备用的模板消息

            @RequestMapping(value = "user/userExInfo", method = RequestMethod.POST)
    @APIPermission(type = 10) 获取个人扩展信息
    userExInfo(Long lastSystemUpdateDate, Long lastPublishInfoUpdateDate, Long lastSpaceInfoUpdateDate, Long lastOtherProjectUpdateDate)

select count(*) from t_msg_basic a where is_active = 0 and ((msg_type like '30%' or (msg_type like '32%' and msg_type != 3200 ) or msg_type = 3200) and (receive_id is null or receive_id = 8281)) and create_time > 0 and not EXISTS( SELECT * from t_msg_ext_read b where b.target_id = a.id and b.target_type = '0' and b.user_type = '2' and b.user_id = 8281 ) 

0(String), 8281(Long), 0(Long), 8281(Long)

select count(*) from t_msg_basic a where is_active = 0 and ((msg_type like '30%' or (msg_type like '32%' and msg_type != 3200 ) or msg_type = 3200) and (receive_id is null or receive_id = 8281)) and create_time > 0 and not EXISTS( SELECT * from t_msg_ext_read b where b.target_id = a.id and b.target_type = '0' and is_delete = 1 and b.user_type = '2' and b.user_id = 8281 ) 
16:37:29.971 [http-nio-8080-exec-4] DEBUG c.b.i.c.m.T.selectCountByParams - ==> Parameters: 0(String), 8281(Long), 0(Long), 8281(Long)

select count(*) from t_publish_basic a where type = ? and is_active = ? and not EXISTS ( SELECT * from t_msg_ext_read b where b.target_id = a.id and b.target_type = '3' and b.user_type = '2' and b.user_id = ? ) 
19:25:09.249 [http-nio-8080-exec-2] DEBUG c.b.i.c.m.T.selectUnreadCountByParams - ==> Parameters: 1(Integer), 0(String), 8281(Long)
19:25:09.263 [http-nio-8080-exec-2] DEBUG c.b.i.c.m.T.selectUnreadCountByParams - <==      Total: 1
19:25:09.265 [http-nio-8080-exec-2] DEBUG c.b.i.c.m.T.selectCountByParams - ==>  Preparing: select count(*) from t_publish_basic where type = ? and is_active = ? 
19:25:09.265 [http-nio-8080-exec-2] DEBUG c.b.i.c.m.T.selectCountByParams - ==> Parameters: 1(Integer), 0(String)


select count(*) FROM t_project_basic tpb LEFT join t_doctor_ext_project tdep on tpb.id=tdep.project_id and tdep.doctor_id=8281 and tdep.is_active=0 where tpb.is_active=0 and tpb.status=40 AND NOT EXISTS ( SELECT 1 FROM t_doctor_ext_project WHERE doctor_id=8281 AND is_active ='0' AND `type` !=0 AND `type` !=4 AND tpb.id=project_id ) AND EXISTS ( SELECT 1 FROM t_template_ext_group b WHERE b.is_active='0' AND b.template_group_id IN ( SELECT a.template_group_id FROM t_template_group_ext_specialty a WHERE a.is_active='0' AND a.specialty_id=2 AND tpb.template_id=template_id ) ) 

19:30:27.765 [http-nio-8080-exec-6] DEBUG c.b.i.c.m.T.selectOtherCountByParams - ==> Parameters: 8281(Long), 0(String), 0(String), 40(Integer), 8281(Long), 2(Long)


select count(*) from t_chat c where to_id = 8281 and direction = 2 and is_receive_read = 0 and is_active = 0 and EXISTS (select id from t_customer_basic cu where is_active = 0 and cu.id = c.send_id) 

19:38:16.985 [http-nio-8080-exec-6] DEBUG c.b.i.c.m.T.findUnReadChatCount - ==> Parameters: 8281(Long), 2(Integer)

SELECT COUNT(*) AS unTplCustomerNums FROM t_customer_ext_hospital AS tceh WHERE (tceh.`status` = 0 OR tceh.`status` = -1) AND tceh.`is_active` = 0 AND tceh.`customer_name` != "示例病人" AND tceh.doctor_id = ? 
19:39:54.470 [http-nio-8080-exec-6] DEBUG c.b.i.c.m.T.findUnTemplateCustomerCount - ==> Parameters: 8281(Long)

1，如果是医生
2，查询未读消息的个数 t_msg_basic  关联  t_msg_ext_read 不包含已读消息
3，最新的系统消息的个数 t_msg_basic 关联  t_msg_ext_read 不包含已删除的消息
4，查询医数发布未读条数 t_publish_basic 关联 t_msg_ext_read 不包含已读
5，查询最新消息个数 t_publish_basic
6,获取其他信息  t_project_basic 关联 t_doctor_ext_project 关联  t_template_ext_group 关联  t_template_group_ext_specialty
7，医聊未读消息数        t_chat 关联 t_customer_basic 患者ID 等于 发送ID
8，获取未分配方案的病人数 t_customer_ext_hospital 

select count(*) from t_space_basic a where type = 2 AND a.create_time > 1450437444000 and not EXISTS ( SELECT * from t_msg_ext_read b where b.target_id = a.id and b.target_type = '4' and b.user_type = 1 and b.user_id = 9287 ) 

select count(*) from t_space_basic where type = 2

select tceh.id, tceh.customer_id, tceh.hospital, tceh.bed_no, tceh.customer_code, tceh.customer_desc, tceh.template_id, tceh.firstPointStartTime,tcb.mobile, tceh.template_name, tceh.status, tceh.create_time, tceh.doctor_id, tceh.doctor_name, tceh.is_active, tceh.im_blocked_at, tceh.remark, tceh.up_time, tceh.mark,tceh.customer_alias,tceh.customerDescContent , tcb.real_name as customer_name, tcb.sex,tcb.age,tcb.face,tcb.rc_token,tcb.birthday,(select count(1) from t_media_relation tmr where tmr.target_id=tceh.id and tmr.target_type='2' and tmr.is_active='0') as remarkNum from t_customer_ext_hospital tceh JOIN t_customer_basic tcb on tceh.customer_id=tcb.id and tcb.is_active = 0 where tceh.status = -1 and tceh.is_active = 0 and tceh.is_active=0 and tceh.status !='9'


select tceh.id, tceh.customer_id, tceh.hospital, tceh.bed_no, tceh.customer_code, tceh.customer_desc, tceh.template_id, tceh.firstPointStartTime,tcb.mobile, tceh.template_name, tceh.status, tceh.create_time, tceh.doctor_id, tceh.doctor_name, tceh.is_active, tceh.im_blocked_at, tceh.remark, tceh.up_time, tceh.mark,tceh.customer_alias,tceh.customerDescContent , tcb.real_name as customer_name, tcb.sex,tcb.age,tcb.face,tcb.rc_token,tcb.birthday,(select count(1) from t_media_relation tmr where tmr.target_id=tceh.id and tmr.target_type='2' and tmr.is_active='0') as remarkNum from t_customer_ext_hospital tceh JOIN t_customer_basic tcb on tceh.customer_id=tcb.id and tcb.is_active = 0 where tceh.customer_id = 9287 and tceh.status in ('1','2') and tceh.is_active = 0 and tceh.is_active=0 and tceh.status !='9' order by CREATE_TIME desc 


select tceh.id, tceh.customer_id, tceh.hospital, tceh.bed_no, tceh.customer_code, tceh.customer_desc, tceh.template_id, tceh.firstPointStartTime,tcb.mobile, tceh.template_name, tceh.status, tceh.create_time, tceh.doctor_id, tceh.doctor_name, tceh.is_active, tceh.im_blocked_at, tceh.remark, tceh.up_time, tceh.mark,tceh.customer_alias,tceh.customerDescContent , tcb.real_name as customer_name, tcb.sex,tcb.age,tcb.face,tcb.rc_token,tcb.birthday,(select count(1) from t_media_relation tmr where tmr.target_id=tceh.id and tmr.target_type='2' and tmr.is_active='0') as remarkNum from t_customer_ext_hospital tceh JOIN t_customer_basic tcb on tceh.customer_id=tcb.id and tcb.is_active = 0 where tceh.status = -1 and tceh.is_active = 0 and tceh.is_active=0 and tceh.status !='9' 

select id, template_name, template_type, status, template_desc, create_time, up_time, start_time, op_id, op_real_name, is_active,type, author, hospital_name, ref_template_id, update_author, doctor_id from t_follow_template where id = 30588

select tceh.id, tceh.customer_id, tceh.customer_name, tceh.hospital, tceh.bed_no, tceh.customer_code, tceh.customer_desc, tceh.template_id, tceh.template_name, tceh.status, tceh.create_time, tceh.doctor_id, tceh.doctor_name, tceh.is_active, tceh.im_blocked_at, tceh.remark, tceh.up_time, tceh.mark, tceh.customer_alias, tceh.customerDescContent,tceh.firstPointStartTime from t_customer_ext_hospital tceh where tceh.customer_id = 9287 and tceh.template_id = 30588 and tceh.doctor_id = 8169 and tceh.is_active = 0 ORDER BY id DESC limit 1;

select a.id, a.template_id, a.point_id,a.point_time, a.link_type, a.link_id, a.link_title, a.sort_by, a.create_time, a.op_id, a.op_real_name, a.is_active, a.is_doctor_only, a.pic, a.subtitle ,ifnull(b.status,'0') as status from t_follow_point_link a left join (select * from t_msg_ext_read where target_type in ('1','2') and user_type = '1' and user_id = 9287 and sub_target_id = 10064 )b on a.id = b.target_id where template_id = 29254 and is_active = 0 order by SORT_BY asc,LINK_TYPE asc,ID asc;

select id, title, sub_title, content, notes_type, content_type, notes_id, op_id, op_real_name, is_active, create_time, author, hospital,pic,status from t_notes_basic where id = 65;


select id, customer_id, customer_name, point_id, point_name, point_date, point_date_desc, template_id, template_name, is_history, doctor_id, doctor_name, create_time, is_active, point_status from t_customer_follow_point where customer_id = 9287 and template_id = 30588 and doctor_id = 8169 and is_active = 0;


customer_id, customer_name, doctor_id, doctor_name, template_id, template_name, survey_id, survey_name, create_time, score, is_active, link_point_id, is_doctor_modify,modify_date from t_customer_survey where customer_id = 9287 and doctor_id = 8169 and template_id = 30588 and is_active = 0;


 select id, doctor_id, doctor_name, customer_id, customer_name, point_id, record_title, record_date, create_time, is_active,template_id from t_customer_point_record where doctor_id = 8169 and customer_id = 9287  and is_active = 0 and template_id = 30583 order by CREATE_TIME asc;




select id, login_name, real_name, password, mobile, city, email, sex,face, status, create_time, is_active,birthday,re_remind,open_id,is_verify_phone,credit_num,app_open_id,real_name_changed,city_changed from t_customer_basic where login_name = '04925655' and is_active = 0 limit 1 ;
# 查询节点信息
select id, customer_id, customer_name, point_id, point_name, point_date, point_date_desc, template_id, template_name, is_history, doctor_id, doctor_name, create_time, is_active, point_status from t_customer_follow_point where customer_id = 9287 and template_id = 30583 and is_history = 1 and doctor_id = 8169 and is_active = 0 order by POINT_DATE asc; 

select id, is_active, create_time, clinicseq, gender, health_card_no, id_card_no, birthday, patient_id, patient_name, doctor_id, doctor_name, visit_date, dept_id, dept_name, diag, icd from t_kingdee_customer_visit_basic where clinicseq = 20161004529;

select id, ifu_customer_id, ifu_customer_name, phone, hospital_id, health_card_no, patient_id, patient_name, is_active, create_time, gender, id_card_no, birthday, dept_id, doctor_id, doctor_name, order_time, reg_date,dept_name from t_kingdee_customer_basic where health_card_no = 04925656 and is_active = 0 limit 1;


select id,eid,base_url,app_id,app_secret,hospital_id, is_active from t_kingdee_config_basic where id = 2

select tceh.id, tceh.customer_id, tceh.hospital, tceh.bed_no, tceh.customer_code, tceh.customer_desc, tceh.template_id, tceh.firstPointStartTime,tcb.mobile, tceh.template_name, tceh.status, tceh.create_time, tceh.doctor_id, tceh.doctor_name, tceh.is_active, tceh.im_blocked_at, tceh.remark, tceh.up_time, tceh.mark,tceh.customer_alias,tceh.customerDescContent , tcb.real_name as customer_name, tcb.sex,tcb.age,tcb.face,tcb.rc_token,tcb.birthday,(select count(1) from t_media_relation tmr where tmr.target_id=tceh.id and tmr.target_type='2' and tmr.is_active='0') as remarkNum from t_customer_ext_hospital tceh JOIN t_customer_basic tcb on tceh.customer_id=tcb.id and tcb.is_active = 0 where tceh.status = -1 and tceh.is_active = 0 and tceh.is_active=0 and tceh.status !='9';

# 老逻辑 须知关联表查询
 select distinct t.template_id, t.point_id, t.point_time, t.sort_by, tp.point_name
    from t_follow_point_link t left join t_follow_template_point tp on t.point_id=tp.id
    where t.template_id= 30583 and t.is_active=0
    order by t.sort_by;

 select count(*) from t_chat c where to_id = 9287 and direction = 1 and is_receive_read = 0 and is_active = 0 and EXISTS (select id from t_doctor_basic cu where is_active = 0 and cu.id = c.send_id);
16:24:14.259 [http-nio-8080-exec-3] DEBUG c.b.i.c.m.T.findUnReadChatCount - ==> Parameters: 9287(Long), 1(Integer)


9，如果是患者
10，未读系统消息的个数     t_msg_basic  关联  t_msg_ext_read 不包含已读消息
11，最新的系统消息的个数   t_msg_basic 关联  t_msg_ext_read 不包含已删除的消息
12，医数发布的未读数      t_publish_basic 关联 t_msg_ext_read 不包含已读
13，最新的医数发布的个数   t_publish_basic
14，医数空间的未读数       t_space_basic 关联    t_msg_ext_read 不包含已读消息
15，最新的医数发布的个数    t_space_basic 
16, 须知的未读数      self.getCustomerNoteUnreadCount(患者基本信息，类型 type = 1)
17, 量表的未读数      self.getCustomerNoteUnreadCount(患者基本信息，类型 type = 0)
18，上两步  查询所有以分组的病例 分组状态 status = 1，患者ID，t_customer_ext_hospital
19, 循环上一步 FollowTemplateService->findCountByTemplateById(病例的模板ID，病例患者ID，0=表单或1=须知类型，病例医生ID，UserType=1患者，2医生)
20，查找模板数据 FollowTemplateService->findCustomerFollowTemplateById（模板ID，患者id, 医生ID，用户类型UserType）
  1，查找模板的数据 t_follow_template
  2，refTemplateId大于0用这条模板ID，否则用上一步的ID
  3，查询病例ID t_customer_ext_hospital 通过 模板ID，医生ID，患者ID，是否有效
  4，查询 方案和须知库、表单的关联信息 (type类型可以直接在sql里处理不需要循环处理)  t_follow_point_link 关联 t_msg_ext_read 表查询 id = target_id
  5,通过上一步的结果循环 查询须知关联表数据 t_notes_basic a 获取须知信息
  6,获取节点信息 t_customer_follow_point 通过 模板ID，医生ID，患者ID，是否有效
  7,上一步取出的数据循环，把pointId当下标拼一个数组（存一个pointDate）
  8，查询所有答题记录 t_customer_survey 通过 模板ID，医生ID，患者ID，是否有效 把linkPointId当下标把整体数据放进去
  9，判断病人是否已经填写表单 循环第4步，通过第8步 通过循环的linkId当第八步下标，看有没有数据，有数据如果数据不为空，分数不为空，须知节点里增加分数，答题，linkID当下标分别拼了一个分数，和一个答题的数组，所有的pointId拼一个数组，pointLink赋值到templatePoint节点里
  10，病程录的拼接，用pointLink.type=2  表示病程录 t_customer_point_record 
  11,查询节点信息 t_customer_follow_point 如果没查到走老的逻辑
  ### 老逻辑 ####
  12,循环遍历 把节点开始时间，节点名称，节点ID放进一个list里面
  13,循环12步把12步通过12步的ID当索引，查看第7步的数组是否包含了这个索引，包含了时间转换为年月日，否则为空
  ### 新逻辑
  14,循环遍历11步查询的节点信息，把节点状态，名称，时间拼数组放进list里面，统计进行中的总数，和所有的总数
  15，统计pointDate不为空的个数
  16，设置pointIndex和pointStatus，如果其它节点时间和当前节点的时间相同，则设置状态为进行中，如果当前时间等于节点开始时间为进行中的，如果状态等于1️已完成的，需要把完成节点的须知和量表设置为已读，获取最后一个节点
  17,如果最后一个节点且节点下的状态为进行中，节点个数不为空，循环节点 如果是患者填写，且状态为0，有未读， 如果全部已读，设置为 allCount  并改变最后节点的状态，如果已读个数大于0，计算完成百分比

  18，查找所有的随访记录,去掉null的
  19,把节点信息，病程录信息加紧节点，把 答题数组，分数数组拼进数组里 返回模板信息，节点信息，须知，量表信息
21，只统计进行中的已读未读
22,统计未读聊天信息 t_chat
23，判断头像是否修改 t_customer_basic

checkUpdateApp
    @RequestMapping(value = "checkUpdateApp", method = RequestMethod.POST)
    checkUpdateApp(HttpServletRequest request, String callback) 校验版本更新


 select count(*) from t_publish_basic where type = 2 and is_active = 0;

      select a.id, a.title, a.sub_title, a.url, a.pic_url, a.create_time, a.type, a.is_active,ifnull(b.status,'0') as status 
      from t_publish_basic a left join t_msg_ext_read b on (a.id = b.target_id and b.target_type = '3' and b.user_type = 1 and b.user_id = 9287) where type = 2 and is_active = 0 order by CREATE_TIME desc limit 0 , 10 
16:43:19.806 [http-nio-8080-exec-4] DEBUG c.b.i.c.m.T.selectListByParams - ==> Parameters: 1(String), 9287(Long), 2(String), 0(String), 0(Integer), 10(Integer)

### 验证码查询
select id, phone, verification, user_type, send_time, invalid_time,code_type from t_verification_basic 
where phone = 13262230057 and verification = 66666 and user_type = 1 and code_type = 3 and is_active = 0 order by invalid_time desc limit 1; 
10:12:07.852 [http-nio-8080-exec-7] DEBUG c.b.i.c.m.T.selectOneByParams - ==> Parameters: 13262230057(String), 66666(String), 1(Integer), 3(Integer), 0(String)
### 查找号码对应的病人
 select id, login_name, real_name, password, mobile, city, email, sex,face, status, create_time, is_active,birthday,re_remind,open_id,is_verify_phone,credit_num,app_open_id,real_name_changed,city_changed from t_customer_basic where mobile = ? and is_active = ? limit 1 
10:32:52.913 [http-nio-8080-exec-7] DEBUG c.b.i.c.m.T.selectByParams - ==> Parameters: 13262230057(String), 0(String)
### 微信登入的病人
select id, login_name, real_name, password, mobile, city, email, sex,face, status, create_time, is_active,birthday,re_remind,open_id,is_verify_phone,credit_num,app_open_id,real_name_changed,city_changed from t_customer_basic where id = 11351
# 10:35:23.991 [http-nio-8080-exec-7] DEBUG c.b.i.c.m.T.selectByPrimaryKey - ==> Parameters: 11351(Long)

### 以分组病人
select count(*) from t_customer_ext_hospital tceh where tceh.customer_id = 11559 and tceh.status in ('1','2') and tceh.is_active = 0 and tceh.is_active=0 and tceh.status !='9';

select tceh.id, tceh.customer_id, tceh.hospital, tceh.bed_no, tceh.customer_code, tceh.customer_desc, tceh.template_id, tceh.firstPointStartTime,tcb.mobile, tceh.template_name, tceh.status, tceh.create_time, tceh.doctor_id, tceh.doctor_name, tceh.is_active, tceh.im_blocked_at, tceh.remark, tceh.up_time, tceh.mark,tceh.customer_alias,tceh.customerDescContent , tcb.real_name as customer_name, tcb.sex,tcb.age,tcb.face,tcb.rc_token,tcb.birthday,(select count(1) from t_media_relation tmr where tmr.target_id=tceh.id and tmr.target_type='2' and tmr.is_active='0') as remarkNum from t_customer_ext_hospital tceh JOIN t_customer_basic tcb on tceh.customer_id=tcb.id and tcb.is_active = 0 where tceh.status = ? and tceh.is_active = ? and tceh.is_active=0 and tceh.status !='9' 
### 未分组病人
select count(*) from t_customer_ext_hospital tceh where tceh.customer_id = 11559 and tceh.status in ('-1','0') and tceh.is_active = 0 and tceh.is_active=0 and tceh.status !='9' 
11:12:06.918 [http-nio-8080-exec-3] DEBUG c.b.i.c.m.T.selectCountByParams - ==> Parameters: 11559(Long), 0(String)


 select id,doctor_ecode, doctor_name, hospital, mobile, email, doctor_desc, sex, department, skill, face, status, id_no, birthday, permit_no, level, create_time, audit_time, audit_op_id, audit_op_real_name, is_active,city,position,hospital_id,department_id,new_cust_re,survy_ok_re,new_temp_re, scene_code, qrcode_ticket, weixin_url, last_audit_info_id, city_id, city_name,credit_num,recommend_id, my_survey_ok_re,specialty_id,specialty_name,position_id,schedule,app_open_id,position_type,level_end_date,level_start_date,doctor_level from t_doctor_basic where mobile = 13800000111 and is_active = 0;
15:41:13.330 [http-nio-8080-exec-2] DEBUG c.b.i.c.m.T.selectByParams - ==> Parameters: 13800000111(String), 0(String)

### 11，根据手机号查询医生
 select id, login_name, op_type, password, real_name, email, mobile, doctor_id, status, create_time, op_id, op_real_name, is_active from t_manage_op_basic where op_type = 1 and is_active = 0 and (login_name = 13800000111 or mobile = 13800000111 or email = 13800000111);
14:56:23.666 [http-nio-8080-exec-5] DEBUG c.b.i.c.m.T.selectByParams - ==> Parameters: 1(String), 0(String), 13800000111(String), 13800000111(String), 13800000111(String)


 select id, login_name, op_type, password, real_name, email, mobile, doctor_id, status, create_time, op_id, op_real_name, is_active from t_manage_op_basic where doctor_id = 8298 and is_active = 0;

 select id, login_name, op_type, password, real_name, email, mobile, doctor_id, status, create_time, op_id, op_real_name, is_active from t_manage_op_basic where op_type = 1 and is_active = 0 and (login_name = 13800000111 or mobile = 13800000111 or email = 13800000111);

select id,doctor_ecode, doctor_name, hospital, mobile, email, doctor_desc, sex, department, skill, face, status, id_no, birthday, permit_no, level, create_time, audit_time, audit_op_id, audit_op_real_name, is_active,city,position,hospital_id,department_id,new_cust_re,survy_ok_re,new_temp_re, scene_code, qrcode_ticket, weixin_url, last_audit_info_id, city_id, city_name,credit_num,recommend_id, my_survey_ok_re,specialty_id,specialty_name,position_id,schedule,app_open_id,position_type,level_end_date,level_start_date,doctor_level from t_doctor_basic where mobile =13800000111 and is_active = 0;
15:45:09.038 [http-nio-8080-exec-3] DEBUG c.b.i.c.m.T.selectByParams - ==> Parameters: 13800000111(String), 0(String)

1，首先判断参数合法性，验证码的有效期
2，VerificationBasicService->checkVerification(手机号，codeType=3同步数据(手机绑定)，用户类型c=1，d=2, 验证码)
2.1，获取万能验证码，如果是万能验证码等于传参验证码直接返回真
2.2，查询数据是否有效，t_verification_basic 时间判断可以放在mysql查询里
2.3，如果有效更新数据状态成已使用返回真  t_verification_basic is_active =1
3，如果是病人
3.1， 查找手机号对应的病人 t_customer_basic
4， 查询微信登入的病人，通过token  t_customer_basic
5， 如果手机病人为空，那么直接绑定手机号到微信病人
6，发送手机短信，设置初始密码 SubmailSmsService->sendWxRegisterSuccessReturn(手机号) 并且返回病人详情数据
7，查询病人，已分组status（1，2），未分组的病例总数status（-1，0）  t_customer_ext_hospital
7.1，如果上一步有数据那么说明是一个深度用户，把微信登入病人的appOpenId更新到这个手机号，把微信登入的病人的账户更新为无效  t_customer_basic 返回用户基本信息
8，如果不是深度用户,把手机查询的用户的信息更新到微信病人里，并且把手机注册病人数据改成删除状态 t_customer_basic
9，去掉用户token，发送短信设置初始密码，返回用户的基本信息
10，如果是医生
10.1，通过token查询微信医生登入信息
11，根据手机号查询医生，如果没有这个用户，那么我们直接把这个手机号码绑定到appWxDoctor上面，
  更新医生手机号，t_doctor_basic
  更新登入信息表的手机号用户名 t_manage_op__basic
  发送重置密码的短信提示   submailSmsService.sendWxRegisterSuccessReturn(mobile)
  返回医生的信息
12，查询医生是否是一个深度用户，通过doctorId查询这个手机用户的doctorBasic t_doctor_basic
13，判断医生是否验证,是否有科室，是否有职称
13.1，有的话代表这个医生是一个深度用户，那么把app_open_id更新到这个医生上面去，
  并且把wxapp医生登入数据删除 和 医生基本数据删除   
  t_doctor_basic   t_manage_op__basic 返回医生基本信息
14，如果不是那么那么我们直接把这个手机绑定到appWxDoctor上面，并且把手机医生账号停掉
15， t_doctor_basic 更新医生手机号，
16，   更新登入信息 t_manage_op__basic
17，   删除传进来的手机号查询的数据 t_doctor_basic  t_manage_op__basic
18，   发送重置密码的短信提示 submailSmsService.sendWxRegisterSuccessReturn(mobile)
19，   返回医生基本信息

ifu/statistics

1，病人注册总数 select count(*) from t_customer_basic where real_name != "示例病人" 
2，微信病人注册数 select count(*) from t_customer_basic where real_name != "示例病人" and open_id IS NOT NULL 
3，非微信病人注册数 select count(*) from t_customer_basic where real_name != "示例病人" and open_id IS NULL 
4，医生注册的总数 select count(*) from t_doctor_basic 
5，H5注册医生注册数 select count(*) from t_doctor_basic where recommend_id IS NOT NULL 
6，非H5注册医生注册 select count(*) from t_doctor_basic where recommend_id IS NULL 
7，已认证医生数 select count(*) from t_doctor_basic where status = 0
8，待审核医生数 select count(*) from t_doctor_basic where status = 4
9，金蝶来的医生 select count(*) from t_kingdee_doctor_basic where ifu_doctor_id is not null 
10，金蝶来的病人 select count(*) from t_kingdee_customer_basic where ifu_customer_id is not null 
11，微信平台授权的C类账户  select count(*) from t_customer_basic tcb, t_wx_user_basic txub where tcb.id = txub.user_id and subscribe = 0
12，至少有一位我的医生并关注公众号的A类病人 elect count(DISTINCT tcb.id) from t_customer_basic tcb, t_customer_ext_hospital tceh where tcb.id = tceh.customer_id and tceh.is_active = '0'and tcb.open_id IS NOT NULL and tcb.real_name != '示例病人' 
13，A类男病人 select count(DISTINCT tcb.id) from t_customer_basic tcb, t_customer_ext_hospital tceh where tcb.id = tceh.customer_id and tceh.is_active = '0'and tcb.open_id IS NOT NULL and tcb.real_name != '示例病人' and tcb.sex = 0
14，A类女病人 select count(DISTINCT tcb.id) from t_customer_basic tcb, t_customer_ext_hospital tceh where tcb.id = tceh.customer_id and tceh.is_active = '0'and tcb.open_id IS NOT NULL and tcb.real_name != '示例病人' and tcb.sex = 1
15，关注公众号但没有医生的B类病人  select count(*) from t_customer_basic where open_id IS NOT NULL and real_name != '示例病人' and id NOT IN (SELECT DISTINCT customer_id FROM t_customer_ext_hospital WHERE is_active = '0') 
16，B类男病人 select count(*) from t_customer_basic where open_id IS NOT NULL and real_name != '示例病人' and id NOT IN (SELECT DISTINCT customer_id FROM t_customer_ext_hospital WHERE is_active = '0') and sex = 0
17，B类女病人 select count(*) from t_customer_basic where open_id IS NOT NULL and real_name != '示例病人' and id NOT IN (SELECT DISTINCT customer_id FROM t_customer_ext_hospital WHERE is_active = '0') and sex = 1
  

  ifu/customerdatas

select 
      DISTINCT tcb.id customerId, tcb.real_name customerName, 
      tcb.sex sex, tcb.birthday birthday, tceh.template_id templateId, 
      tceh.template_name templateName, tceh.doctor_name doctorName 
from 
  t_customer_basic tcb, 
  t_customer_ext_hospital tceh 
where tcb.id = tceh.customer_id and tceh.is_active = '0'and tcb.open_id IS NOT NULL and tcb.real_name != '示例病人' and tceh.template_id > '0';

50%
a,b,b,c,c,c,b,c,c,b,


select count(1) from t_chat where direction=1 and is_active = 0 and send_id=8298 and to_id=11351 and create_time >= 1476892800000 and create_time <= 1476979199000; 
13:38:44.817 [http-nio-8080-exec-8] DEBUG c.b.i.c.m.T.selectCountByParams - ==> Parameters: 1(Integer), 0(String), 8298(Long), 11351(Long), 1476892800000(Long), 1476979199000(Long)
13:38:44.824 [http-nio-8080-exec-8] DEBUG c.b.i.c.m.T.selectCountByParams - <==      Total: 1
13:38:44.886 [http-nio-8080-exec-8] DEBUG c.b.i.c.m.T.selectListByParams - ==>  Preparing: select id, reply_chat_id, reply_id, reply_user_type, reply_name, direction, send_id, send_name, to_id, to_name, create_time, content, content_type, send_mobile_type, is_active,type, is_receive_read, send_face_url, to_face_url, content_duration from t_chat where direction=? and is_active = ? and send_id=? and to_id=? and create_time >= ? and create_time <= ? limit ? , ? 
13:38:44.886 [http-nio-8080-exec-8] DEBUG c.b.i.c.m.T.selectListByParams - ==> Parameters: 1(Integer), 0(String), 8298(Long), 11351(Long), 1476892800000(Long), 1476979199000(Long), 0(Integer), 10(Integer)


1，判断发送消息的是 病人还是医生  拼装 发送人 id 姓名 头像
2，如果发送人是医生
2.1，查询病人的基本信息，通过toId 如果没有数据直接return， 获取姓名和头像
2.2，判断是否为微信病人
2.3，判断医生的职称
2.4，self::handleMsg(内容类型，接收消息人信息，发送内容，发送人基本信息)
2.4.1，推送消息 如果失败了就用48小时默认模板
2.5，判断是否为医生当天第一次给微信病人发送消息 是:向病人推送图文消息，如果图文消息发送不成功则发送文本消息 self::doctorPushCustomerWxMsg(医生信息，病人信息)
2.5.1 获取当前当天医生向病人发送的消息列表,拼装数据，查询总条数 t_chat
2.6， 如果是当天第一条 向病人推送消息 WechatTemplateSendService->pushImageTextToWXCustomerByDoctor(接收人基本信息，发送人基本信息，url)
2.6.1，图片宽高处理 100px  WechatTemplateSendService->getLitleFaceUrl(头像url)
2.6.2，获取背景图，医生名，消息内容，查看信息按钮，拼接消息
2.6.3，发送消息  WechatTemplateSendService->pushWxCustomerMessage(拼接消息内容，接受消息人信息，发送消息人信息，信息标题)
2.6.4，推送消息 WxMpService->customMessageSend() 
2.6.5，添加一条消息记录  WechatTemplateSendService->addWxTempMsgToServer(接受消息让微信ID, 内容, 微信url, 发送人基本信息)
2.6.6 查询病人基本信息 t_customer_basic
      查询医生基本信息 t_doctor_basic
      获取医生职称  DoctorPositionService->getShortTitleById(职称ID)
      新增推送记录  t_wx_template_msg_ext_customer
2.6.7  如果发送消息失败，发送48小时失联的备用模板 WechatTemplateSendService->pushStanbyTemplateMsg(接收人基本信息，发送人基本信息，内容，url)
      WechatTemplateSendService->templateSend()
      WxMpService->templateSend()
3，添加一条微信发送消息记录 t_chat
4，如果发送消息的是患者，查询医生的信息，名称，头像 t_doctor_basic
5，重复第三步
6，查找病历数据，看是否是家标的 t_customer_ext_hospital 
7，查询五分钟之内的发送消息的条数，如果五分钟内是两条的话直接 t_chat return 
8，如果不超过2条查询这个消息  t_chat 
9，推送 MsgPushFacade->pushChatMsgByCustomerToDoctor(发送人基本信息，接收人基本信息，聊天记录)
9.1，PushNotificationFacade->pushMsgToDoctor(接收人基本信息，title，发送内容，【消息类型，发送人ID】)
9.1.2,  用户推送Channel表 查询 ostype t_push_channel  没有数据 return 有数据 查找用户老数据  PushNotificationFacade->pushMsgToChannelId()

    @RequestMapping(value = "list", method = RequestMethod.POST)
    @APIPermission(type = 10)
    list(Long toId, int page, Long lastUpdateDate)


select id,doctor_ecode, doctor_name, hospital, mobile, email, doctor_desc, sex, department, skill, face, status, id_no, birthday, permit_no, level, create_time, audit_time, audit_op_id, audit_op_real_name, is_active,city,position,hospital_id,department_id,new_cust_re,survy_ok_re,new_temp_re, scene_code, qrcode_ticket, weixin_url, last_audit_info_id, city_id, city_name,credit_num,recommend_id, my_survey_ok_re,specialty_id,specialty_name,position_id,schedule,app_open_id,position_type,level_end_date,level_start_date,doctor_level from t_doctor_basic where id = 8298;
# 15:48:38.282 [http-nio-8080-exec-1] DEBUG c.b.i.c.m.T.selectByPrimaryKey - ==> Parameters: 8298(Long)

select id, login_name, op_type, password, real_name, email, mobile, doctor_id, status, create_time, op_id, op_real_name, is_active from t_manage_op_basic where doctor_id = 8298 and is_active = 0;
# 15:48:38.294 [http-nio-8080-exec-1] DEBUG c.b.i.c.m.T.selectByParams - ==> Parameters: 8298(Long), 0(String)
select count(1) from t_chat where is_active = 0 and ((send_id= 8298 and to_id = 11351 and direction= 1) or(to_id= 8298 and send_id = 11351 and direction= 2 )); 

select id, reply_chat_id, reply_id, reply_user_type, reply_name, direction, send_id, send_name, to_id, to_name, create_time, content, content_type, send_mobile_type, is_active,type, is_receive_read, send_face_url, to_face_url, content_duration from t_chat where is_active = 0 and ((send_id= 8298 and to_id = 11351 and direction= 1) or(to_id= 9298 and send_id = 11351 and direction= 2)) order by ID desc limit 0 , 10;


    /**
     * 我的聊天对象列表
     * @param token
     * @param callback
     * @param page
     * @return
     */
    @RequestMapping(value = "myFriendlist", method = RequestMethod.POST)
    @APIPermission(type = 10)
    myFriendlist( int page)

      select id, reply_chat_id, reply_id, reply_user_type, reply_name, direction, send_id, send_name, to_id, 
      to_name, create_time, content, content_type, send_mobile_type, is_active,type, is_receive_read, 
      send_face_url, to_face_url, content_duration 
      from t_chat 
      where is_active = 0 and ((send_id= 11351 and to_id = 8298 and direction= 2) or(to_id= 11351 and send_id = 8298 and direction= 1)) order by CREATE_TIME desc limit 1;
15:35:12.608 [http-nio-8080-exec-2] DEBUG c.b.i.c.m.T.selectOneByParams - ==> Parameters: 0(String), 11351(Long), 8298(Long), 2(Integer), 11351(Long), 8298(Long), 1(Integer)


 select id, reply_chat_id, reply_id, reply_user_type, reply_name, direction, send_id, send_name, to_id, to_name, create_time, content, content_type, send_mobile_type, is_active,type, is_receive_read, send_face_url, to_face_url, content_duration from t_chat where is_active = 0 and ((send_id= 9287 and to_id = 8169 and direction= 2) or(to_id= 9287 and send_id = 8169 and direction= 1)) order by CREATE_TIME desc limit 1 

selectOneByParams - ==> Parameters: 0(String), 9287(Long), 8169(Long), 2(Integer), 9287(Long), 8169(Long), 1(Integer)



    @RequestMapping(value = "cityList", method = RequestMethod.POST)
    list(String callback, String token, String cityName)

      1，获取病人基本信息    t_customer_basic
      2，获取城市列表 up_id = 0 所以数据  t_city_basic
      select id, city_name, up_id, up_name, type, is_active,is_hot from t_city_basic where up_id = 0 and is_active = 0

        /**
     * 获取地区列表
     * */
    @RequestMapping(value = "areaList", method = RequestMethod.POST)
    areaList(String callback, String token, Long upId)



    /**
     * 医院列表
     * */
    @RequestMapping(value = "hospList", method = RequestMethod.POST)
    hospList(String callback, String token, Long cityId)


      select t.id, t.hospital_name, t.city_id, t.is_active,area_id,c.parent_id as 'parentId' , c.name, c.parent_id as parentId,
      d.name as parentName 
      from t_hospital_basic t LEFT JOIN t_area_basic c ON t.area_id=c.id LEFT JOIN t_area_basic d ON d.id=c.parent_id where t.is_active = 0 and t.city_id = 22
# 16:30:11.132 [http-nio-8080-exec-8] DEBUG c.b.i.c.m.T.selectListByParams - ==> Parameters: 0(String), 22(Long)


          /**
     * 科室列表
     * */
    @RequestMapping(value = "deptList", method = RequestMethod.POST)
    deptList(String callback, String token, Long hospitalId)

      select id, login_name, real_name, password, mobile, city, email, sex,face, status, create_time, is_active,birthday,re_remind,open_id,is_verify_phone,credit_num,app_open_id,real_name_changed,city_changed from t_customer_basic where id = 9287

      select id, hospital_id, department_id, hospital_name, department_name,up_depId from t_hospital_ext_department;

select id, login_name, real_name, password, mobile, city, email, sex,face, status, create_time, is_active,birthday,re_remind,open_id,is_verify_phone,credit_num,app_open_id,real_name_changed,city_changed from t_customer_basic where id = 11351;

    /**
     * 扫描二维码
     */
    @RequestMapping(value = "scanQRCode", method = RequestMethod.POST)
    @APIPermission(type = 1)
    scanQRCode(String wxUrl, String weixinUrl)
        if (StringUtils.isBlank(wxUrl))
            wxUrl = weixinUrl
        }

    afa57f4695954071ab149f4d0e6845b7

  1，验证空的验证，获取病人的信息 t_customer_basic
  2，获取医生的信息 FollowTemplateService->getDoctorByWxUrl(wxUrl)

      /**
     * 客户（病人）登录
     * @param callback
     * @param loginName
     * @param password
     * @return
     */
    @RequestMapping(value = "login", method = RequestMethod.POST)
    login(String loginName, String password)

    1，customerBasicService->login(用户名，密码)
    2，查询有没有这个用户 t_customer_basic
    3，判断密码正不正确  （用数据库做） 返回用户基本信息
    4，TokenCacheUtil->getToken(缓存名称，token前缀，用户ID，true=是否是重新创建一次新的) 
      每次登入删除原来的token生成一个新的token
      token生成用的是一个uuid
      缓存token值  cacheTemplate.set(platformTokenKey.key + userId, token) 
      缓存用户ID cacheTemplate.set(platformTokenKey.key + token, String.valueOf(userId))
      返回 token 
    5，返回用户的基本信息

        /**
     * 病人注销
     * @param token
     * @param callback
     * */
    @RequestMapping(value = "logout", method = RequestMethod.POST)
    @APIPermission(type = 1)
    logout(String callback, String token)

1，查询有没有这个病人
2，删除缓存的token
  cacheTemplate.delete(platformTokenKey.key + token)
  cacheTemplate.delete(platformTokenKey.key + userId)
3，首先查询有没有推送记录  t_push_channel
4，如果有的话就删除这条记录  t_push_channel 并返回



    /**
     * 病人注册
     * @param callback
     * @param loginName
     * @param password
     * @param mobile
     * @param realName
     */
    @RequestMapping(value = "register", method = RequestMethod.POST)
    register(String callback, String loginName, String password, String realName, String checkCode)

    1，验证手机号，密码，验证码
    2，查询数据是不是已经被注册 t_customer_basic
    3，customerBasicService->register(注册信息) 插入一条注册信息
    4，插入成功生成一个新的token TokenCacheUtil.getToken(cacheTemplate, CommonConstant.PlatformTokenKey.CommonCustomer, registerCustmer.id)
    5，生成一个随机的头像 RandomFaceUtil->returnRandomFace(-1) 并且返回信息

      /**
     * 病人基本信息
     * */
      RandomFaceUtil.isNeedUpdateRandomFace(customerBasic.getFace(), customerBasic.getSex())

      customerBasic




token:40ef9a0058f0481a97954e3f9061bdfd

select id, login_name, real_name, password, mobile, city, email, sex,face, status, create_time, is_active,birthday,re_remind,open_id,is_verify_phone,credit_num,app_open_id,real_name_changed,city_changed from t_customer_basic where id = 11615;

select id, login_name, real_name, password, mobile, city, email, sex,face, status, create_time, is_active,birthday,re_remind,open_id,is_verify_phone,credit_num,app_open_id,real_name_changed,city_changed from t_customer_basic where mobile = 13300000001 and is_active = 0 limit 1;

select count(*) from t_customer_ext_hospital tceh where tceh.customer_id = 30 and tceh.status in ('1','2') and tceh.is_active = 0 and tceh.is_active=0 and tceh.status !='9';
          /**
     * 同步病人的手机号码
     * @param mobile
     * @param checkCode
     * @param userType
     */
    @RequestMapping(value = "synUser", method = RequestMethod.POST)
    @APIPermission(type = 1)
    synUser(String mobile, String checkCode)

1，验证手机号，验证码有效，
2，查找修改的手机号是否存在，
  如果通过token找到的患者基本信息 和 通过手机号查到的基本信息相同，
  或者 传参手机号查询出来的数据为空 更新手机号
  并且发送短信初始密码设置 
  返回病人信息

3，如果这个手机号码的病人没有医生的前提上,才可以做同步,
4，查询病例记录是否有正在进行中或者已完成的数据，如果有说明该手机号被其他微信病人使用 直接返回
5，如果该手机号没有绑定医生更新通过token查询出来的数据
6，把之前的手机号病人改成删除状态
7，去掉这个用户的token
8，发送手机信息，设置初始密码




cusBasic  {"face":"http://qiniu.ifuifu.com/img/origin/14703174577246.png","city":"闵行区","realName":"吃货","birthday":"1986-06-15","reRemind":"0","sex":"0"}

    /**
     * 修改病人基本信息
     * */
    @RequestMapping(value = "edit", method = RequestMethod.POST)
    @APIPermission(type = 1)
    edit(String cusBasic)


1，通过token查询微信医生登入信息
2，检查信息的完整性，手机号，真实姓名，生日
3，如果修改的里面有手机号码,则先判断本身是否是认证手机号码,如果是则不允许修改
4，查看即将修改的手机号码是否被其他人使用过,如果是则不允许修改 t_customer_basic
5，修改用户数据
6，如果病人信息不完善，则完善信息后，检测是否需要添加医数值  self::checkNeedAddCreditNumToDoctor()
7，判断是否需要给医生添加医数值(新规则：医生分配病人方案，只有当病人提交了病历和完善了个人信息，才添加) 
8, 循环处理病例列表
9，添加医术值 CreditLogService->add()
9.1,验证医生是否已经审核
9,2，医生不能为空
9,3，返回boolean = 如果医生等级等于一，当前时间大于会员生效时间，且当前时间小于会员结束时间，或者会员结束时间为空
9,4，医生关联病例表信息    t_customer_ext_hospital 如果查询的值不等于空,返回的boolean = 医生等级等于一，病例更新时间大于会员开始时间，病例更新时间小于会员结束时间，或者会员结束时间为空
9,5，查询医术值规则，医术值规则不能为空 t_credit_ext_rule
9,6，如果第5步 all_limit限制次数大于0 单日限制次数,查询log表里的记录对比总条数是否等于限制次数，等于就return   t_credit_log
9,7，如果类型为4=分配方案，5=自建方案升级到官方方案，如果有 targetId 搜索条件带上 targetId
9,8，如果是分配病人并且有其他医生已经给该病人分配过方案医数值加1,如果是新的分配病人医术值加15 t_credit_log
9,9，如果该医生已给病人分配方案添加医数值直接return  t_credit_log
9,10，如果总限制次数等于0 或者 所以记录次数小于总限制次数 添加一条日志记录  t_credit_log  更新医生的医术值  t_doctor_basic
10，如果用户修改了头像和姓名，那么要把推送的消息提醒中的头像和姓名信息更改回来
11，处理realname或者face更新后的相关性的其他数据的更新 self::operationCustomerChangeExt(customerBasic1)
11.1，更新头像 t_msg_basic
11.2，更新病例病人名称 t_customer_ext_hospital
11.3，更新聊天记录 患者和医生 t_chat
  

  修改提醒设置
    @RequestMapping(value = "modifySetting", method = RequestMethod.POST)
    @APIPermission(type = 1)
    modifySetting(String reRemimd)

    /**
     * 找回密码
     */
    @RequestMapping(value = "retrieveCustomerPassword", method = RequestMethod.POST)

    retrievePassword(String callback, String loginName, String checkCode, String password)

1，验证手机号，验证码是否有效
2，通过手机号查询是否有这个患者，t_customer_basic
3，有数据然后就修改这条数据的密码



    /**
     * 医数空间
     */
    @RequestMapping(value = "ifuSpace", method = RequestMethod.POST)
    @APIPermission(type = 1)
    ifuSpace(String token)
    /**
     * 医数发布
     * @param token
     * @return
     */
    @RequestMapping(value = "publishIfu", method = RequestMethod.POST)
    @APIPermission(type = 1)
    publishIfu(String token)

    /**
     *
     * 修改密码接口
     */
    @RequestMapping(value = "customerModifyPassword", method = RequestMethod.POST)
    @APIPermission(type = 1)
    modifyPassword(String callback, String token, String oldPassword, String newPassword)

1，通过token查询病人基本信息
2，ICustomerBasicService->login(用户名，旧的密码)
2.1，通过手机号查询患者基本信息， 验证用户密码，返回患者基本信息 （用户密码可以用数据库来验证的）
3，如果上一步返回了基本信息， ICustomerBasicService->findPassword(用户名，新密码) 
3.1，更新用户密码 并且 删除用户token

    /**
     *验证手机号接口
     *暂时只支持患者端验证，如需验证医生端请继续拓展
     * add huyucheng
     */
    @RequestMapping(value = "doVerifyMobile", method = RequestMethod.POST)
    doVerifyMobile(String mobile, String token){

1，验证手机号，手机格式
2，通过token查询出病人的基本信息 t_customer_basic
3，通过手机号查找病人 t_customer_basic
4，没找到相应的病人或者病人自己 直接返回

/**
 *患者端账号替换接口
 * 只修改t_customer_basic表is_active并为修改方案，节点，量表，须知相关信息
 * add by huyucheng
 */
@RequestMapping(value = "replaceAccount", method = RequestMethod.POST)
replaceAccount(String mobile, String checkCode, String token){

1，验证手机号，验证码
2，通过token查询出病人的基本信息  t_customer_basic
3，通过手机号查询病人的基本信息   t_customer_basic
4，没找到相应的病人 更新登入名称，手机号 t_customer_basic 
  发送重置密码的短信提示，返回基本信息
5，该手机已经绑定该病人 更新手机号，并且返回基本信息
6，存在已绑定改手机号的患者，作废该账号，废除通过手机号查找出来的这个数据 t_customer_basic
7，绑定手机号，t_customer_basic
8，发送手机信息，设置初始密码
9，去掉这个用户的token 返回数据


    @RequestMapping(value = "list", method = RequestMethod.POST)
    list(String callback, String token)
1，通过token查询病人基本信息
2，查询是不是已分组的病人 t_customer_ext_hospital
3，FollowTemplateService->findFollowPointListByTemplateById(病例的模板ID，须知类型=1)
3.1，通过模板ID查询模板记录  t_follow_template
3.2，如果有数据且 refTemplateId>0 通过 refTemplateId查找 模板记录
3.3，查询 方案和须知库、表单的关联信息 t_follow_point_link 
     循环处理数据，获取所有的节点ID， 节点ID当下标，把节点激活时间存进去，把节点数据存在list里
4，查询节点信息，通过上一步获得的节点ID列表 t_follow_template_point 
5，拼节点时间，和节点的须知，返回数据


/**
     * 查看须知库
     * @param callback
     * @param token
     * @param notesId
     * @return
     */
//    @APIPermission(type = 1, platformTokenKey = CommonConstant.PlatformTokenKey.CommonCustomer)
    @RequestMapping(value = "{notesId}", method = RequestMethod.POST)

    detail(@PathVariable("notesId") Long notesId, Long pointId, Long customerExtHosId)
1，查找须知详情，通过须知ID  t_notes_basic
2，判断contentType 是否为 2 答题 查询 数据拼到详情数据里 t_note_temp

    }
    /**
     * 更新须知库里的缩略图和副标题
     */
    @RequestMapping(value = "updateTitle", method = RequestMethod.POST)
    updateTitle(int page)
select id, title, sub_title, content, notes_type, content_type, notes_id, op_id, op_real_name, is_active, create_time, author, hospital,pic,status from t_notes_basic where content like '%http://ms.ifuifu.com/Index/detail/id/%' and (status is null or status!=0);
16:28:30.479 [http-nio-8080-exec-9] DEBUG c.b.i.c.m.T.findListByContent - ==> Parameters: 

1，查询 t_notes_basic 总条数
2，循环 更新符合条件的数据


    }
    /**
     * 新增须知答题 李龙
     * @param customerExtHosId
     * @param pointId
     * @param noteId
     * @param score
     * @return
     */
    @APIPermission(type = 1)
    @RequestMapping(value = "answer", method = RequestMethod.POST)
    answer(Long customerExtHosId, Long pointId, Long noteId, String score)

1，查询病人的基本信息，通过拦截器
2，通过须知ID查询须知记录      t_notes_basic
3，通过病例ID，查询病例数据    t_customer_ext_hospital
4，通过须知ID，病例ID，查询答题记录 t_note_temp
5，对比病人的ID判断病人有么有权限答题，有权限就答题，答题表插入一条记录 t_note_temp


int a = Cont>0 ? Cont*pageSize : 0

if (Cont>0)a = Cont*pageSize} else {a = 0}
    /**
     * 查看表单
     * @param callback
     * @param token
     * @param surveyId
     * @return
     */
    @RequestMapping(value = "{surveyId}", method = RequestMethod.POST)
    detail(String callback, String token,
           @PathVariable("surveyId") Long surveyId, Long doctorId, Long linkPointId, Long customerExtHosp)

 select id, login_name, real_name, password, mobile, city, email, sex,face, status, create_time, is_active,birthday,re_remind,open_id,is_verify_phone,credit_num,app_open_id,real_name_changed,city_changed from t_customer_basic where id = 11351


select tceh.id, tceh.customer_id, tceh.hospital, tceh.bed_no, tceh.customer_code, tceh.customer_desc, tceh.template_id, tceh.firstPointStartTime,tcb.mobile, tceh.template_name, tceh.status, tceh.create_time, tceh.doctor_id, tceh.doctor_name, tceh.is_active, tceh.im_blocked_at, tceh.remark, tceh.up_time, tceh.mark,tceh.customer_alias,tceh.customerDescContent,tceh.in_progress_point_time , tcb.real_name as customer_name, tcb.sex,tcb.age,tcb.face,tcb.rc_token,tcb.birthday,(select count(1) from t_media_relation tmr where tmr.target_id=tceh.id and tmr.target_type='2' and tmr.is_active='0') as remarkNum from t_customer_ext_hospital tceh JOIN t_customer_basic tcb on tceh.customer_id=tcb.id and tcb.is_active = 0 where tceh.customer_id = 11351 and tceh.doctor_id = 8170 and tceh.is_active = 0 and tceh.is_active=0 and tceh.status !='9'

select id, title, tag, survey_desc, survey_type, origin_type, survey_id, status, template, answer_limit, op_id, op_real_name, is_active, create_time, is_doctor_only from t_survey_basic where id = 6

select id, survey_id, question_title, question_type, question_code, is_answer, is_show, setting, sort_by, up_question_id, is_random,is_template,is_system, create_time, op_id, op_real_name, is_active from t_survey_question where survey_id = 6 and is_active = 0

select id, survey_id, question_id, option_code, option_text,option_score, sort_by, is_random, setting, create_time, op_id, op_real_name, is_active,pic from t_survey_option where survey_id = 6 and is_active = 0;

select tceh.id, tceh.customer_id, tceh.customer_name, tceh.hospital, tceh.bed_no, tceh.customer_code, tceh.customer_desc, tceh.template_id, tceh.template_name, tceh.status, tceh.create_time, tceh.doctor_id, tceh.doctor_name, tceh.is_active, tceh.im_blocked_at, tceh.remark, tceh.up_time, tceh.mark, tceh.customer_alias, tceh.customerDescContent,tceh.firstPointStartTime from t_customer_ext_hospital tceh where tceh.id = 13971;

select id, template_id, point_id,point_time, link_type, link_id, link_title, sort_by, create_time, op_id, op_real_name, is_active, is_doctor_only, pic, subtitle from t_follow_point_link where id = 69390;

select id, template_name, template_type, status, template_desc, create_time, up_time, start_time, op_id, op_real_name, is_active,type, author, hospital_name, ref_template_id, update_author, doctor_id from t_follow_template where id = 31445;

select tceh.id, tceh.customer_id, tceh.customer_name, tceh.hospital, tceh.bed_no, tceh.customer_code, tceh.customer_desc, tceh.template_id, tceh.template_name, tceh.status, tceh.create_time, tceh.doctor_id, tceh.doctor_name, tceh.is_active, tceh.im_blocked_at, tceh.remark, tceh.up_time, tceh.mark, tceh.customer_alias, tceh.customerDescContent,tceh.firstPointStartTime from t_customer_ext_hospital tceh where tceh.customer_id = 11351 and tceh.template_id = 31445 and tceh.doctor_id = 8170 and tceh.is_active = 0 ORDER BY id DESC limit 1;

select a.id, a.template_id, a.point_id,a.point_time, a.link_type, a.link_id, a.link_title, a.sort_by, a.create_time, a.op_id, a.op_real_name, a.is_active, a.is_doctor_only, a.pic, a.subtitle ,ifnull(b.status,'0') as status from t_follow_point_link a left join (select * from t_msg_ext_read where target_type in ('1','2') and user_type = '1' and user_id = 11351 and sub_target_id = 13971 )b on a.id = b.target_id where template_id = 1253 and is_active = 0 order by SORT_BY asc,LINK_TYPE asc,ID asc;

select id, title, sub_title, content, notes_type, content_type, notes_id, op_id, op_real_name, is_active, create_time, author, hospital,pic,status from t_notes_basic where id = 1187;

select id, title, sub_title, content, notes_type, content_type, notes_id, op_id, op_real_name, is_active, create_time, author, hospital,pic,status from t_notes_basic where id = 1188;

select id, title, sub_title, content, notes_type, content_type, notes_id, op_id, op_real_name, is_active, create_time, author, hospital,pic,status from t_notes_basic where id = 1197;

select id, title, sub_title, content, notes_type, content_type, notes_id, op_id, op_real_name, is_active, create_time, author, hospital,pic,status from t_notes_basic where id = 903;

select id, title, sub_title, content, notes_type, content_type, notes_id, op_id, op_real_name, is_active, create_time, author, hospital,pic,status from t_notes_basic where id = 1189;

select id, title, sub_title, content, notes_type, content_type, notes_id, op_id, op_real_name, is_active, create_time, author, hospital,pic,status from t_notes_basic where id = 904;

select id, title, sub_title, content, notes_type, content_type, notes_id, op_id, op_real_name, is_active, create_time, author, hospital,pic,status from t_notes_basic where id = 905;

select id, title, sub_title, content, notes_type, content_type, notes_id, op_id, op_real_name, is_active, create_time, author, hospital,pic,status from t_notes_basic where id = 843;

select id, title, sub_title, content, notes_type, content_type, notes_id, op_id, op_real_name, is_active, create_time, author, hospital,pic,status from t_notes_basic where id = 1199; 

select id, title, sub_title, content, notes_type, content_type, notes_id, op_id, op_real_name, is_active, create_time, author, hospital,pic,status from t_notes_basic where id = 1195;

select id, title, sub_title, content, notes_type, content_type, notes_id, op_id, op_real_name, is_active, create_time, author, hospital,pic,status from t_notes_basic where id = 1190;

select id, customer_id, customer_name, point_id, point_name, point_date, point_date_desc, template_id, template_name, is_history, doctor_id, doctor_name, create_time, is_active, point_status from t_customer_follow_point where customer_id = 11351 and template_id = 31445 and doctor_id = 8170 and is_active = 0; 

select id, customer_id, customer_name, doctor_id, doctor_name, template_id, template_name, survey_id, survey_name, create_time, score, is_active, link_point_id, is_doctor_modify,modify_date from t_customer_survey where customer_id = 11351 and doctor_id = 8170 and template_id = 31445 and is_active = 0;

select id, doctor_id, doctor_name, customer_id, customer_name, point_id, record_title, record_date, create_time, is_active,template_id from t_customer_point_record where doctor_id = 8170 and customer_id = 11351 and is_active = 0 and template_id = ? order by CREATE_TIME asc;

select id, customer_id, customer_name, point_id, point_name, point_date, point_date_desc, template_id, template_name, is_history, doctor_id, doctor_name, create_time, is_active, point_status from t_customer_follow_point where customer_id = 11351 and template_id = 31445 and is_history = 1 and doctor_id = 8170 and is_active = ? order by POINT_DATE asc;

select id, customer_id, customer_name, doctor_id, doctor_name, template_id, template_name, survey_id, survey_name, create_time, score, is_active, link_point_id, is_doctor_modify,modify_date from t_customer_survey where customer_id = 11351 and doctor_id = 8170 and survey_id = 6 and is_active = 0 and link_point_id = 69390 limit 1;

select t.id, t.customer_survey_id, t.customer_id, t.survey_id, t.question_id, t.option_id, t.option_text, t.option_value, t.option_score, t.create_time, t.is_active , tsq.question_code, tsq.question_title from t_customer_survey_detail t LEFT JOIN t_survey_question tsq on t.question_id=tsq.id where t.customer_survey_id = 4754 and t.customer_id = 11351 and t.survey_id = 6 and t.is_active = 0 order by CUSTOMER_ID asc ;

1，查询病人的基本信息，通过toId
2，self::findSurveyBasic(量表ID，病人基本信息，医生ID，须知关联表ID，病例ID)
2.1，如果doctorId存在,校验是否存在随访 t_customer_ext_hospital 如果没有返回错误提示
2.2，查询量表记录  t_survey_basic
2.3，判断随访记录ID存不存在，存在查询记录 t_customer_ext_hospital 
    判断状态是否已解除关系，
    判断数据的有效性，
    否则量表的分数赋值为-1
2.4，查询须知关联表，通过须知关联表ID，判断数据是否有效，有效把须知关联表isDoctorOnly 赋值给 量表的isDoctorOnly属性
2.5，如果量表的 isDoctorOnly 为 0 直接返回 错误提示
2.6，如果街边未开始则，量表的分数赋值 -1，FollowTemplateService->findCustomerFollowTemplateById(模板ID，患者ID，医生ID，用户类型=1)
2.6.1，查找模板的数据 t_follow_template
2.6.2，refTemplateId大于0用这条模板ID，否则用上一步的ID
2.6.3，查询病例ID t_customer_ext_hospital 通过 模板ID，医生ID，患者ID，是否有效
2.6.4，查询 方案和须知库、表单的关联信息 (type类型可以直接在sql里处理不需要循环处理)  t_follow_point_link 关联 t_msg_ext_read 表查询 id = target_id
2.6.5，通过上一步的结果循环 查询须知关联表数据 t_notes_basic a 获取须知信息
2.6.6，获取节点信息 t_customer_follow_point 通过 模板ID，医生ID，患者ID，是否有效
2.6.7，上一步取出的数据循环，把pointId当下标拼一个数组（存一个pointDate）
2.6.8，查询所有答题记录 t_customer_survey 通过 模板ID，医生ID，患者ID，是否有效 把linkPointId当下标把整体数据放进去
2.6.9，判断病人是否已经填写表单 循环第4步，通过第8步 通过循环的linkId当第八步下标，看有没有数据，有数据如果数据不为空，分数不为空，须知节点里增加分数，答题，linkID当下标分别拼了一个分数，和一个答题的数组，所有的pointId拼一个数组，pointLink赋值到templatePoint节点里
2.6.10，病程录的拼接，用pointLink.type=2  表示病程录 t_customer_point_record 
2.6.11,查询节点信息 t_customer_follow_point 如果没查到走老的逻辑
  ### 老逻辑 ####
2.6.12,循环遍历 把节点开始时间，节点名称，节点ID放进一个list里面
2.6.13,循环12步把12步通过12步的ID当索引，查看第7步的数组是否包含了这个索引，包含了时间转换为年月日，否则为空
  ### 新逻辑 ###
2.6.14,循环遍历11步查询的节点信息，把节点状态，名称，时间拼数组放进list里面，统计进行中的总数，和所有的总数
2.6.15，统计pointDate不为空的个数
2.6.16，设置pointIndex和pointStatus，如果其它节点时间和当前节点的时间相同，则设置状态为进行中，如果当前时间等于节点开始时间为进行中的，如果状态等于1️已完成的，需要把完成节点的须知和量表设置为已读，获取最后一个节点
2.6.17,如果最后一个节点且节点下的状态为进行中，节点个数不为空，循环节点 如果是患者填写，且状态为0，有未读， 如果全部已读，设置为 allCount  并改变最后节点的状态，如果已读个数大于0，计算完成百分比

2.6.18，查找所有的随访记录,去掉null的
2.6.19,把节点信息，病程录信息加紧节点，把 答题数组，分数数组拼进数组里 返回的列表
3，查询用户有没有答案 t_customer_survey 
4，如果是填空题或者手绘题添加节点
5，判断有没有答题
6，把里面大于等于2的list剔除掉




select id, customer_id, customer_name, point_id, point_name, point_date, point_date_desc, template_id, template_name, is_history, doctor_id, doctor_name, create_time, is_active, point_status from t_customer_follow_point where customer_id = 11351 and template_id = 31260 and is_history = 1 and is_active = 0;
/**
 * 查看要填写的表单  TODO: POST没有这个测试，有用吗？
 * @param callback
 * @param token
 * @return
 */
@RequestMapping(value = "current", method = RequestMethod.POST)
current(String callback, String token, Long doctorId, Long linkPointId)

1，查询病人的基本信息，通过token
2，查询随访记录 t_customer_ext_hospital
3，查询节点表 t_customer_follow_point
4，需要查询已经填写过的表单 t_customer_survey
5，查询所有表单 
  查询须知关联表数据信息列表
  通过关联列表状态，如果时间大于当前时间或等于现在
6，self::findSurveyBasic(量表ID，病人基本信息，医生ID，须知关联表ID，病例ID)
6.1，如果doctorId存在,校验是否存在随访 t_customer_ext_hospital 如果没有返回错误提示
6.2，查询量表记录  t_survey_basic
6.3，判断随访记录ID存不存在，存在查询记录 t_customer_ext_hospital 
    判断状态是否已解除关系，
    判断数据的有效性，
    否则量表的分数赋值为-1
6.4，查询须知关联表，通过须知关联表ID，判断数据是否有效，有效把须知关联表isDoctorOnly 赋值给 量表的isDoctorOnly属性
6.5，如果量表的 isDoctorOnly 为 0 直接返回 错误提示
6.6，如果街边未开始则，量表的分数赋值 -1，FollowTemplateService->findCustomerFollowTemplateById(模板ID，患者ID，医生ID，用户类型=1)
6.6.1，查找模板的数据 t_follow_template
6.6.2，refTemplateId大于0用这条模板ID，否则用上一步的ID
6.6.3，查询病例ID t_customer_ext_hospital 通过 模板ID，医生ID，患者ID，是否有效
6.6.4，查询 方案和须知库、表单的关联信息 (type类型可以直接在sql里处理不需要循环处理)  t_follow_point_link 关联 t_msg_ext_read 表查询 id = target_id
6.6.5，通过上一步的结果循环 查询须知关联表数据 t_notes_basic a 获取须知信息
6.6.6，获取节点信息 t_customer_follow_point 通过 模板ID，医生ID，患者ID，是否有效
6.6.7，上一步取出的数据循环，把pointId当下标拼一个数组（存一个pointDate）
6.6.8，查询所有答题记录 t_customer_survey 通过 模板ID，医生ID，患者ID，是否有效 把linkPointId当下标把整体数据放进去
6.6.9，判断病人是否已经填写表单 循环第4步，通过第8步 通过循环的linkId当第八步下标，看有没有数据，有数据如果数据不为空，分数不为空，须知节点里增加分数，答题，linkID当下标分别拼了一个分数，和一个答题的数组，所有的pointId拼一个数组，pointLink赋值到templatePoint节点里
6.6.10，病程录的拼接，用pointLink.type=2  表示病程录 t_customer_point_record 
6.6.11,查询节点信息 t_customer_follow_point 如果没查到走老的逻辑
  ### 老逻辑 ####
6.6.12,循环遍历 把节点开始时间，节点名称，节点ID放进一个list里面
6.6.13,循环12步把12步通过12步的ID当索引，查看第7步的数组是否包含了这个索引，包含了时间转换为年月日，否则为空
  ### 新逻辑 ###
6.6.14,循环遍历11步查询的节点信息，把节点状态，名称，时间拼数组放进list里面，统计进行中的总数，和所有的总数
6.6.15，统计pointDate不为空的个数
6.6.16，设置pointIndex和pointStatus，如果其它节点时间和当前节点的时间相同，则设置状态为进行中，如果当前时间等于节点开始时间为进行中的，如果状态等于1️已完成的，需要把完成节点的须知和量表设置为已读，获取最后一个节点
6.6.17,如果最后一个节点且节点下的状态为进行中，节点个数不为空，循环节点 如果是患者填写，且状态为0，有未读， 如果全部已读，设置为 allCount  并改变最后节点的状态，如果已读个数大于0，计算完成百分比

6.6.18，查找所有的随访记录,去掉null的
6.6.19,把节点信息，病程录信息加紧节点，把 答题数组，分数数组拼进数组里 返回的列表



answer

1，判断存不存在 customerExtHosp ID，如果不存在跑老的方法
  oldAnswer("", token, surveyId, doctorId, linkPointId, answerContent, templateId)
2,



    ApiResultHelper 
    oldAnswer(String callback, String token, Long surveyId, Long doctorId, Long linkPointId, String answerContent, Long templateId)


1，查询随访记录 t_customer_ext_hospital 如果没有数据直接返回 （通过传过来的随访ID查询）
2，查询量表记录 t_survey_basic 如果没有数据直接返回
3，查询须知关联表记录 t_follow_point_link 如果数据有效那么 surverBasic.isDoctorOnly = followPointLink.isDoctorOnly
4, 如果isDoctorOnly是0 医生那么直接返回
5，查看有没有答题，t_customer_survey，如果已经答题了的话直接return
6，处理json 拼装分数，添加一条答题记录 ，t_customer_survey
7，修改随访状态 self::updateCusExtHos(病例信息)
7.1，查询 refTemplateId ID t_follow_template
7.2，查出当前节点之后的节点的量表 t_follow_point_link
7.3，与病人回答量表的数据比较未答得的量表则不修改status 状态修改成2 t_customer_ext_hospital
8，通过病例的doctorId查询病人的信息
9，如果第六步插入成功 增加一个百度推送 并且 t_msg_basic 添加一条记录日志
10，发送聊天消息，新增一条聊天记录


     */
    @RequestMapping(value = "answer", method = RequestMethod.POST)
    @APIPermission(type = 1)
    answer(String token, Long linkPointId, String answerContent, Long customerExtHosp, Long surveyId, Long templateId, Long doctorId)









/**
 * 扫描二维码
 */
@RequestMapping(value = "scanQRCode", method = RequestMethod.POST)
@APIPermission(type = 1)
scanQRCode(String wxUrl, String weixinUrl)

1，获取患者基本信息，通过拦截器
2，self::getDoctorByWxUrl(wxUrl) 获取医生的信息
2.1，也可能是方案二维码,因为方案二维码存储在memcached,所以优先判断
2.2，这个url可能是医生的名片二维码 通过这个二维码去数据库查找数据  t_doctor_basic
3，FollowTemplateService->getTemplateByTemplateWXUrl(wxUrl) 获取模板信息
3.1，

获取省市区列表

    @RequestMapping(value = "areaList", method = RequestMethod.GET)
    getAreaList(String callback,  Long id, String name)

t_area_basic


t_console_user_basic

    /**
     * 客服后台用户列表
     * @return
     */
    @RequestMapping(value = "getConsoleUser", method = RequestMethod.POST)
    getConsoleUser(String id)

    /**
     * 客服后台用户列表
     * @return
     */
    @RequestMapping(value = "pageList", method = RequestMethod.POST)
    pageList(RequestHelper requestHelper)


    /**
     * 客服后台用户列表
     * @return
     */
    @RequestMapping(value = "save", method = RequestMethod.POST)
    save(TConsoleUserBasic consoleUserBasic)  {

    /**
     * 客户列表(所有的)
     * @return
     */
    @ConsolePermission(code="console:customerService")
    @RequestMapping(value = "list", method = RequestMethod.GET)




    /**
     * 常量查询
     * @return
     */
    @RequestMapping(value = "constant", method = RequestMethod.GET)
    list(String constantName)

@RestController
@RequestMapping("consoleApi/op")
class OpApi {

1，验证手机号，密码 ConsoleUserBasicService->login(用户名，密码)
1.1，查询登入的客户信息通过用户名，判断登入密码是否正确
1.2，判断登入觉得的权限
2，生成一个新的token TokenCacheUtil.getToken
3，返回数据

    /**
     * 客服后台登录
     * @param loginName
     * @param password
     * @return
     */
    @ConsolePermission(code = "console:customerService")
    @RequestMapping(value = "", method = RequestMethod.GET)
    op(String token)

    /**
     * 客服后台注销
     * @return
     */
    @RequestMapping(value = "logout", method = RequestMethod.GET)
    logout(String token)


    /**
     * 各种错误转到此页面，进行ajax输出
     * @param errCode
     */
    @RequestMapping(value="error/{errCode}")  errCode

    /**
     * 项目列表
     * @returnl
     */
    @ConsolePermission(code="console:customerService")
    @RequestMapping(value = "listAll", method = RequestMethod.GET)
    listAll(RequestHelper requestHelper)

1，查询总条数 t_project_basic
2，查询列表 t_project_basic
3，循环列表，如果项目的字段模板ID 大于0 查询模板数据，通过模板ID统计 随访记录的总条数
4，查询发起人信息 t_doctor_ext_project
5， self::selectCountHospitalByProjectId(项目ID) 统计医院的总数，根据项目ID t_doctor_ext_project
 

     /**
     * 项目详情
     * @return
     */
    @ConsolePermission(code="console:customerService")
    @RequestMapping(value = "{id}", method = RequestMethod.GET)
    detail(@PathVariable("id") Long id)

1，判断id是否大于0
2，ProjectService->detail(id)
2.1，不查询我在项目的状态  doctorId = -1  ProjectService->detail（id,-l）
2.2，查找项目ID t_project_basic
2.3，把多中心项目发起人的相关信息查询出来 t_doctor_ext_project
2.4，如果doctorId ！= -1  再次查询 t_doctor_ext_project 通过医生ID，项目ID  把当前医生和这个项目的关联信息描述进去
2.5，通过templateId来查询这个项目的方案模板  t_follow_template
2.6，有多少个病历是使用这个多中心项目的方案的 t_doctor_ext_project
2.7，把未完成随访节点的病人数目统计出来 t_customer_follow_point 等钱时间大于节点时间 
2.8，self::selectAvgProgress(templateId)
2.8.1， 查询随访节点总数 t_customer_follow_point
2.8.2， 查询随访节点完成总数 t_customer_follow_point
2.8.3，总数大于0 计算出平均数
2.9，统计病例总数 t_customer_ext_hospital
2.10，统计已完成的病例总数 t_customer_ext_hospital  status=2
2.11，计算出病例平均数 t_customer_ext_hospital
2.12，参与该项目的医院数目 self::selectCountHospitalByProjectId(项目ID)  t_doctor_ext_project
2.13，参与该项目的医生数目 self::selectCountDoctorByProjectId(项目ID)   


    /**
     * 参与人员信息
     * @return
     */
    @ConsolePermission(code="console:customerService")
    @RequestMapping(value = "{id}/attendList", method = RequestMethod.GET)
    attendList(@PathVariable("id") Long id) 

1，ProjectService->.attendList(id)
2，添加类型 types = [1, 2, 3]
3，self::findDocExtProList(projectId, types)
3.1，self::findObjByKey(projectId)  t_project_basic
3.2，t_doctor_ext_project 查找医生项目关联表



    /**
     * 修改参与人员权限
     * @return
     */
    @ConsolePermission(code="console:customerService")
    @RequestMapping(value = "setAttendPermission", method = RequestMethod.POST)
    setAttendPermission(Long id, Integer type)
1，ProjectService->setAttendPermission(id, type)
2，通过ID 修改 type t_doctor_ext_project




    /**
     * 将项目状态设置为方案制作中
     * @returnl
     */
    @ConsolePermission(code="console:customerService")
    @RequestMapping(value = "{id}/setToTemplateProduction")
    setToTemplateProduction(@PathVariable("id") Long id)

1，ProjectService->setToTemplateProduction(projectId)
2，self::findObjByKey(projectId) 通过项目ID查找数据  t_project_basic
3，判断状态是不是已申请状态
4，通过项目ID，发起人状态，查找项目医生关联记录 t_doctor_ext_project
5，通过上一步查找的数据得到的医生ID，查找医生的基本信息，判断是否是已审核医生
6，更新方案成制作中 self::modifyBasic(project)
7，submailSmsService->sendProjectMakeProject(mobile,title)    发送短信
8，msgPushFacade->pushDoctorProjectMakeTemp(doctor, project)  发送推送


/**
 * 申请加入的详情
 */
@ConsolePermission(code="console:customerService")
@RequestMapping(value = "apply/{id}", method = RequestMethod.GET)
applyDetail(@PathVariable("id") Long id)

t_doctor_ext_project

/**
 * 申请加入 同意
 */
@ConsolePermission(code="console:customerService")
@RequestMapping(value = "apply/{id}/approve", method = RequestMethod.POST)
applyApprove(@PathVariable("id") Long id)

    if (!id || !(id > 0)) return new ResultHelper(resCode: "A004")

    return new ResultHelper(resCode: projectService.applyApprove(id).resCode)
}

1，ProjectService->applyApprove(id)
2，通过id查询项目医生关联表数据，     t_doctor_ext_project
  通过查出来的项目ID查询项目数据，    t_project_basic
  通过项目数据查询的模板ID查询模板数据 t_follow_template
  通过医生关联项目表医生ID查询医生的基本信息，验证是否已审核  t_doctor_basic
3，修改项目关联表类型，t_doctor_ext_project （普通医生，管理员两个状态）
4，添加多中心方案到(申请人)我的方案里  t_manage_op_basic 通过上一步doctor_id
5，添加记录  t_follow_template
6, 发送短信,推送: 多中心，增加参与者时 及时推送（被添加者
6.1，submailSmsService.sendProjectAddActor(doctorExtProject.mobile, projectBasic.title)
6.2，msgPushFacade.pushDoctorProjectAddPlayer(doctorBasic, projectBasic)


/**
 * 申请加入 忽略
 */
@ConsolePermission(code="console:customerService")
@RequestMapping(value = "apply/{id}/ignore", method = RequestMethod.POST)
applyIgnore(@PathVariable("id") Long id)

1，查询医生项目关联表数据             t_doctor_ext_project
2，更新病人医生项目关联表type=12 忽略 t_doctor_ext_project


    /**
     *
     * @return
     */

    @ConsolePermission(code="console:customerService")
    @RequestMapping(value = "getHospital", method = RequestMethod.POST)
    getHospital( String id)


   /**
     *分页查询医院列表
     * @return
     */

    @ConsolePermission(code="console:customerService")
    @RequestMapping(value = "pageList", method = RequestMethod.POST)
    pageList(RequestHelper requestHelper)
t_hospital_basic

    /**
     * 受邀用户 完成
     */
    @ConsolePermission(code="console:customerService")
    @RequestMapping(value = "apply/{id}/finish", method = RequestMethod.POST)
    applyFinish(@PathVariable("id") Long id)
    

    /**
     * 添加/修改医院
     * @return
     */

    @ConsolePermission(code="console:customerService")
    @RequestMapping(value = "saveHospital", method = RequestMethod.POST)
    saveHospital( String cusBasic)

1，没有传id就新增一条数据
2，检查医院存不存在 t_hospital_basic
3，新增一条记录  t_hospital_basic
4，查询刚刚新增的医院  t_hospital_basic
5，查询3个默认的科室 t_department_basic
6，问新增医院添加默认科室 t_hospital_basic
7，如果ID不为空则修改  t_hospital_ext_department


        param["startTime"] =startTime;
        param["endTime"] =endTime;
        param["marketId"]=id;

统计
select m.id, m.market_team_id, m.console_user_id, m.name, m.sex, m.mobile,m.hiredate, m.remark,COUNT(d.id) as  doctorNum
    ,SUM(IF(d.status='0',1,0)) as doctorAuditNum
    ,SUM(IF(d.status='0' and d.audit_time >=0 and d.audit_time <=0,1,0)) as doctorAuditNumNew
    ,SUM((SELECT COUNT(DISTINCT customer_id) FROM t_customer_ext_hospital  ext where ext.doctor_id= d.id and customer_name !='示例病人' and ext.is_active=0 )) as patientNumAll
    ,SUM((SELECT COUNT(DISTINCT customer_id) FROM t_customer_ext_hospital  ext where ext.doctor_id= d.id and customer_name !='示例病人' and ext.up_time >=0 and ext.up_time <=0 and ext.status=1 and ext.is_active=0 )) as patientNumNew
    ,SUM((SELECT COUNT(DISTINCT customer_id) FROM t_customer_ext_hospital  ext where ext.doctor_id= d.id and customer_name !='示例病人' and ext.is_active=0 and ext.`status`=1)) as patientNumIsGroup
    ,SUM((SELECT COUNT(DISTINCT customer_id) FROM t_customer_ext_hospital  ext where ext.doctor_id= d.id and customer_name !='示例病人' and ext.is_active=0 and ext.`status`=0)) as patientNumNoGroup
    FROM t_doctor_basic d
    LEFT JOIN t_market_ext_hospital mh on mh.hospital_id=d.hospital_id and mh.is_active=0
    LEFT JOIN t_market_basic m on m.id= mh.market_id and m.is_active=0
    where m.id=4 AND  d.is_active=0
    GROUP BY m.id;

1，MarketBasicService->detail(参数) t_market_basic
2，MarketBasicService->getMarketStatisticByMarketId(startTime，endTime，marketId)
3，self::findObjByKey()   查询销售基本信息 t_market_basic 
4，销售医院关联表 记录查询   t_market_ext_hospital
5，统计随便记录表的记录  t_customer_ext_hospital   t_market_ext_hospital t_market_basic
6，销售医院关联表 记录通过marketId  t_market_ext_hospital
7，通过上一步查出的数据循环首先通过上一步的查询的数据中的医院ID统计医生总数 t_doctor_basic
8，如果总数大于0 


Snapchat Instagram
    /**
     * 扫描二维码
     */
    @RequestMapping(value = "scanQRCode", method = RequestMethod.POST)
    @APIPermission(type = 1)
    scanQRCode(String wxUrl, String weixinUrl) {

      t_follow_point_link

1，通过拦截去获取病人基本信息
2，通过方法获取医生基本信息self::getDoctorByWxUrl(wxUrl)
2.1，方案二维码在缓存里首先判断是否是方案二维码
2.2，如果不是方案二维码就通过wxUrl查询医生的基本信息（医生名片二维码） t_doctor_basic
3，根据方案二维码获取方案 FollowTemplateService->getTemplateByTemplateWXUrl(wxUrl)
3.1，获取缓存的模板ID，通过模板ID查询出方案数据 t_follow_template
3.2，如果有数据判断方案是否启用 status=0
3.3，判断是否有数据如果有的话 判断 refTemplateId = template.refTemplateId > 0 ? template.refTemplateId : template.id
3.4，FollowTemplateService->checkHasPointTime(refTemplateId)
3.4.1，t_follow_point_link 通过ID查找所有节点信息，循环判断节点的周期，如果为空返回一个false
4，self::operationScanQRCode(customerBasic, doctorBasic, template) 逻辑处理




    /**
     * 代码封装,把info,scanQRCode和detail的接口代码放在在一起
     * @param customerBasic
     * @param doctorBasic
     * @param template
     */
    private operationScanQRCode(TCustomerBasic customerBasic, TDoctorBasic doctorBasic, TFollowTemplate template) {

1，没有提交的病例查找 ICustomerExtHospitalService->getOrCreateUnSubmitCustomerExtHospital(doctorBasic, customerBasic, template)

1，根据医生ID，病人ID查询有效的病例
2，如果有病例我们就循环处理病例
3，如果病例的状态为未提交
3.1.1，判断传进来的方案对象存在不存在，如果有方案有改变,则修改
  （模板ID，方案创建时间，方案名称）t_customer_ext_hospital
3.1.2，分配方案 DoctorExtTemplateGroupService->confirmCustomer(doctorBasic, customerBasic, template, customerExtHospital)
3.1.3，如果病人提交了病历，并且手机号码也填写了，则添加医数值 creditLogService.add(医术值类型, 医生信息, 患者id)
3.2.1，未分组的情况,下直接补充病例,并且把病例的状态改为已分组
3.2.2，分配方案 DoctorExtTemplateGroupService->confirmCustomer(doctorBasic, customerBasic, template, customerExtHospital)
3.2.3，creditLogService.add(医术值类型, 医生信息, 患者id)
3.3，如果未分组 customerExtHospitalResult = customerExtHospital
3.4，已分组病人,扫描的是已经分配的方案 （发送微信推送，被注释了） return customerExtHospitalResult
4，走到这步，代表该医生和病人之间不存在病例，那么我们创建一个新的病例，状态为为提交，因为我们这里是扫描方案二维码进来的
5，扫完之后填写病例信息之后状态才会变成未分组，然后医生再分配方案最终状态变成已经分组
6，如果template=null 提醒医生有新的病人  msgPushFacade.pushDoctorForConfrimTemplateWithCustomer(医生信息, 患者信息, 随访记录)
7，如果方案不为空，并且方案是启用状态中， 修改病历状态 status=0
8， 如果新病人扫描的是医生的方案二维码,则直接变为已分组病人  DoctorExtTemplateGroupService->confirmCustomer(医生信息, 患者信息, 模板信息, 随访记录)
9，上一步分配成功修改随访记录状态为已分组 status = 1 
10，新增医术值 如果病人提交了病历，并且手机号码也填写了，则添加医数值 creditLogService.add(医术值类型, 医生信息, 患者id)
11，把查询随访记录返回数据
     







DoctorExtTemplateGroupService->confirmCustomer(doctorBasic, customerBasic, template, customerExtHospital)

1，查询医生登入信息
2，如果模板的操作人ID，不等于上一步查询的ID  return
3，判断方案是否停用
4，检查节点的时候是否为空 point_date  FollowTemplateService->checkHasPointTime(refTemplateId) 查询 t_follow_link_point 循环判断
5，如果医生已经给患者分配方案那么报错返回
6，CustomerExtHospitalService->findObj() 查询已分组的随访记录
7，获取方案节点的默认每一个pointId t_follow_link_point获取第一条数据的pointId 通过 refTemplateId
8，将t_customer_ext_hospital status = 1 改成以分组
9，节点处理 CustomerExtHospitalService->newConfirmCustomer(病人信息, 医生信息, 模板名称, 接口开始时间, 模板ID, 默认几点ID, 所有节点数据, 设置ture/false)
10，提醒病人已被分配新方案 如果有随访记录备注走微信推送，否则走友盟推送
    self::noticeWxCustomerDoctorConfirmResult(医生信息, 病人信息, 随访记录, 分组状态, 默认节点ID)
    msgPushFacade.pushDoctorConfirmCustomerMsg(医生信息, 病人信息, 随访记录, 分组状态, 默认节点ID)
11，病人扫描方案二维码后医生端收到推送 msgPushFacade->pushDoctorForCustomerScanTemplateWeixinUrl(病人信息, 随访记录, 医生信息)

扫描方案二维码提交病情之后的处理逻辑

CustomerExtHospitalService->newConfirmCustomer(病人信息, 医生信息, 模板名称, 接口开始时间, 模板ID, 默认几点ID, 所有节点数据, 设置ture/false)

    //
    public TCustomerExtHospital newConfirmCustomer(TCustomerBasic customerBasic, TDoctorBasic doctorBasic, String templateName, String firstPointStartTime, long templateId, long pointId, List<TFollowPointLink> distinctPointLinkList,Boolean isResetting) {
        Long customerId = customerBasic.id

1，如果设置为真，通过医生ID，病人ID，查询随访记录表 t_customer_ext_hospital
2，上一步的记录不为空的时候继续 如果是模板ID = null 则为第一次进入 更新记录 或者 传过来的模板ID = 上一步查出来的模板ID 且 开关=false 更新记录 t_customer_ext_hospital
2.1，否则新增一条记录 t_customer_ext_hospital 通过 第一步的ID = target_id  附件关联表ID，关联去除所有数据，在重新新增 t_media_relation （240行疑问，先把数据查询出来，把查询出来的数据又插入了一次）
2.2，设置时间节点  先找，再创建
2.2.1，删除旧的病程录信息       t_customer_point_record
       删除旧的随访节点信息     t_customer_follow_point
       删除旧的量表量 级 表答案 t_customer_survey t_customer_survey_detail
2.2.2，增加随访节点信息  t_customer_follow_point
3，删除示例病人 （先查询，再删除） t_customer_basic




    /**
     * 已注册医生列表
     * @return
     */
    @ConsolePermission(code = "console:customerService")
    @RequestMapping(value = "register/list", method = RequestMethod.GET)
    registerList(RequestHelper requestHelper) {


      t_doctor_basic



          /**
     * 已注册医生详情
     * @return
     */
    @ConsolePermission(code = "console:customerService")
    @RequestMapping(value = "register/{id}", method = RequestMethod.GET)
    registerDetail(@PathVariable("id") Long id) {


    /**
     * 医生注册
     * @param callback
     * @param loginName
     * @param password
     * @param userName
     * @param checkCode
     * @return
     */
    @ConsolePermission(code = "console:customerService")
    @RequestMapping(value = "addOpAndDoctor", method = RequestMethod.POST)
    addOpAndDoctor( TDoctorBasic doctorBasic) {

    //添加模拟病人
        customerBasic = new TCustomerBasic(loginName: customerLoginName.toString(), mobile: customerLoginName.toString(), realName: "示例病人", password: cusPassword, birthday: -134208000000)
        addBasic(customerBasic)

        //写入病人医生关系表

1，首先查询手机号有没有被医生使用（被使用返回错误信息）       t_doctor_basic
2，查询医生登入表里面有没有手机号记录(有数据返回错误)   t_manage_op_basic 
3，查询城市名称 t_city_basic
4，通过专业ID查询医生的 方案组ID=>专业ID  t_template_group_ext_specialty
5，添加方案组处理 DoctorExtTemplateGroupService->saveDoctorExtTemplateGroup(ids(传参方案组ID), templateGroupIds(查询方案组ID), 医生ID)
5.1，通过对比传参的方案组是否包含在查询出来的方案组ID里面，如果没有先查询数据库里面有没有记录 t_doctor_ext_template_group ，如果没有新增一条记录
6，如果传参没有传方案组ID那么，通过医生ID删除所有分组关联记录 t_doctor_ext_template_group
7，注册 doctorBasicService->register(doctorBasic, PasswordHelper.md5("111111"))
7.1，根据手机号查询医生信息表，如果存在账号，那么代表注册过了，返回null   t_doctor_basic
7.2，如果没有注册过，那么我们生成一个账号 如果插入失败返回 0
7.3，在客服后台系统里面插入医生信息 t_manage_op_basic 
     如果医生是认证过了,则直接改成正常.这是用于一些外部同步过来的医生,注册以后就直接是认证了
7.4，给账号权限 DoctorBasicService->setRolesByOp(权限（默认1），操作员ID)
     首先删除所有的老的权限 t_manage_op_role
     新增一条新的权限  t_manage_op_role
7.5，增加模拟病人 customerBasicService->getOrCreateSimulationCustomerByDoctorId(doctorBasic)
7.5.1， 默认用户名  customerLoginName = 10800000000 + doctorBasic.id
7.5.2，查询有没有这个用户名有的话直接返回  t_customer_basic
7.5.3，添加模拟病人 t_customer_basic
7.5.4，写入病人医生关系表 t_customer_ext_hospital



    /**
     * 修改医生信息
     * @param doctor
     */
    @ConsolePermission(code = "console:customerService")
    @RequestMapping(value = "register/save", method = RequestMethod.POST)
    registerSave(String doctorStr) {



      /**
     * 查询 待审核的医生
     * @param requestHelper
     * @return
     */
    @ConsolePermission(code = "console:customerService")
    @RequestMapping(value = "list/audit", method = RequestMethod.GET)
    listAudit(RequestHelper requestHelper) {



            //生成医生二维码
            if (CommonConstant.DoctorStatus.Verify.value.equals(doctor.status)) {
                checkAndGenerateWeixinQrCode(doctor)

                //认证成功给推荐医生添加医数值
                if (doctor.recommendId != null && doctor.recommendId > 0) {

                    params = [:]
                    params["isActive"] = CommonConstant.IsActive.True.value;
                    params["userId"] = doctor.recommendId;
                    params["targetId"] = doctor.id;
                    params["type"] = CommonConstant.CreditType.InviteRegister.value;

                    int count = creditLogService.findCountByParams(params)

                    if (count == 0) {
                        TDoctorBasic recommendDoctor = (TDoctorBasic) doctorBasicService.findObjByKey(doctor.recommendId)
                        creditLogService.add(CommonConstant.CreditType.InviteRegister.value, recommendDoctor, doctor.id)
                    } else {
                        log.info("doctor id {} has add credit ", doctor.recommendId)
                    }
                }
    /**
     * 审核 医生
     * @param id
     * @return
     */
    @ConsolePermission(code = "console:customerService")
    @RequestMapping(value = "audit", method = RequestMethod.POST)
    audit(HttpServletRequest request) {

1，首先查询认证表信息   t_doctor_audit_info
2，查询医生信息 ，通过上一步查询的医生ID t_doctor_basic
3，验证可以审核的状态，3,4,1,6
4，审核提示
    已审核，
    submailSmsService.sendModifyMessage(doctor.mobile, doctor.doctorName);
    msgPushFacade.pushDoctorModifyMsg(doctor);
    已退回状态，
    submailSmsService.sendFailToSendModify(doctor.mobile, auditMessage);
    msgPushFacade.pushDoctorModifyMsgFail(doctor);
    都会发送短信提示，友盟推送提示
5，更新 
   医生信息， t_doctor_basic
   认证信息   t_doctor_audit_info
6，更新或者添加网站账户
  首先查操作表有没有数据，没有数据新增，有数据修改 t_manage_op_basic
7，生成医生二维码
   checkAndGenerateWeixinQrCode(doctor)
8，认证成功给推荐医生添加医数值
  首先查询，然后在添加医术值 t_credit_log

    /**
     * 退回重新审核 医生
     * @param id
     * @param message
     * @return
     */
    @ConsolePermission(code = "console:customerService")
    @RequestMapping(value = "unAudit", method = RequestMethod.POST)
    unAudit(@RequestParam("id") Long id, @RequestParam("message") String message) {
1，新增一条认证记录  t_doctor_audit_info
2，将上一步新增ID更新到医生信息里  t_doctor_basic
3，如果失败提示 = 管理员要求重新认证 发送短信和推送重新提示
submailSmsService.sendDoctorUnaudit(doctor.mobile, message);
msgPushFacade.pushDoctorUnAudit(doctor);

    /**
     * 已审核医生列表
     * @return
     */
    @ConsolePermission(code = "console:customerService")
    @RequestMapping(value = "verify/list", method = RequestMethod.GET)
    verifyList(RequestHelper requestHelper) {

1，获取医生信息  t_doctor_basic
2，通过上一步循环获取医生纸质名片信息 t_apply_card_log


    /**
     * 已审核医生详情
     * @return
     */
    @ConsolePermission(code = "console:customerService")
    @RequestMapping(value = "verify/{id}", method = RequestMethod.GET)
    verifyDetail(@PathVariable("id") Long id) {

1，通过ID查询医生详情 t_doctor_basic
2，生产医生二维码 checkAndGenerateWeixinQrCode(doctorBasic)
3，再次查询医生详情，因为生产二维码的时候会更新医生记录
4，获取审核备注 t_doctor_audit_info
5，获取纸质名片信息 返回所有的数据

doctorConsoleApi
    /**
     * 修改医生信息
     * @param doctor
     */
    @ConsolePermission(code = "console:customerService")
    @RequestMapping(value = "verify/edit", method = RequestMethod.POST)
    verifyEdit(TDoctorBasic doctor) {

1，t_doctor_basic
2，t_manage_op_basic


    /**
     * 医数值记录列表
     * @return
     */
    @ConsolePermission(code = "console:customerService")
    @RequestMapping(value = "creditLogList", method = RequestMethod.GET)
    creditLogList(RequestHelper requestHelper) {



        //查询医数值日志
        RollPage rollPage = creditLogService.findListPageByParams(param, order, requestHelper.page, null);

1，查询医数值日志列表 t_credit_log
2，查询医生医数值总分 t_credit_log
3，待审核奖励总分 rewardStatus=1
        //查询医生医数值总分
        int countCredit= creditLogService.selectDoctorCredit(param);

        param["rewardStatus"] =1;
        //待审核奖励总分

    /**
     * 提现
     * @return
     */
    @ConsolePermission(code = "console:customerService")
    @RequestMapping(value = "presentMoney", method = RequestMethod.POST)
    presentMoney(Long doctorId,int creditNum) {


  1，首先查询医生的总医术值，然后判断体现的医术值是或否大于总医术值 t_doctor_basic
  2， creditLogService.add(体现状态-1000, 医生信息, null,体现医术值)
  2.1，新增体现医术值记录
  2.2，计算出剩余的医术值，
       然后更新医生基本信息的医术值


    /**
     * 修改医数值日志奖励状态
     * @return
     */
    @ConsolePermission(code = "console:customerService")
    @RequestMapping(value = "upRardStatus", method = RequestMethod.POST)
    upRardStatus(Long doctorId,Long creditLogId,String status) {

    }
    /**
     * 已申请名片列表
     * @return
     */
    @ConsolePermission(code = "console:customerService")
    @RequestMapping(value = "applyCard/list", method = RequestMethod.GET)
    applyCardList(RequestHelper requestHelper) {


1，查询名片信息列表
2，循环上一步，通过医生ID查询医生记录，
    如果没有医生记录，更新状态 is_active=1 无效

    /**
     * 已申请名片详情
     * @return
     */
    @ConsolePermission(code = "console:customerService")
    @RequestMapping(value = "applyCard/{id}", method = RequestMethod.GET)
    applyCardDetail(@PathVariable("id") Long id) {

1，查询名片详情记录 t_apply_card_log
2，判断数据是否有效
3，通过上一步获取的ID查询医生记录 t_doctor_basic
4，查询审核信息，通过上一步查询的审核ID，获取审核备注，返回数据 t_doctor_audit_info

    /**
     * 修改名片信息
     * @param doctor
     * @param applyCardLog
     */
    @ConsolePermission(code = "console:customerService")
    @RequestMapping(value = "applyCard/edit", method = RequestMethod.POST)
    applyCardEdit(@RequestParam("doctor") String doctorRequestStr, @RequestParam("applyCardLog") String applyCardLogReqestStr) {
        try {
1，通过传参的医生信息更新医生基本信息 t_doctor_basic
2，更新医生操作表 t_manage_op_basic
3，更新医生名片表 t_apply_card_log




    /**
     * 获取省市区列表
     * @param callback
     * @param token
     * @param id
     * @param name
     * @return
     */
    @RequestMapping(value = "areaList", method = RequestMethod.GET)
    getAreaList(Long id, String name) {

t_area_base


    /**
     * 医院列表
     * */
    @RequestMapping(value = "hospList", method = RequestMethod.GET)
    hospList(Long areaId, Integer page, Long cityId) {

    /**
     * 科室列表
     * */
    @RequestMapping(value = "deptList", method = RequestMethod.GET)
    deptList(Long hospitalId) {

t_hospital_basic
t_hospital_ext_department  up_depId

    /**
     * 亚专业列表
     * @param specialtyId
     * @return
     */
    @RequestMapping(value = "templateGroupList", method = RequestMethod.GET)
    templateGroupList(Long specialtyId) {

      t_template_group_basic

    /**
     * 专业列表
     * @param parentId
     * @return
     */
    @RequestMapping(value = "specialtyList", method = RequestMethod.GET)
    specialtyList(Long parentId) {

    /**
     * 医生职称列表
     */
    @RequestMapping(value = "positionList", method = RequestMethod.GET)
    doctorPositionList() {

t_specialty_basic





    /**
     * 查询 城市 列表
     * @return
     */
    @RequestMapping(value = "city", method = RequestMethod.GET)
    city() {

      t_area_base

    /**
     * 获取地区列表
     * */
    @RequestMapping(value = "area", method = RequestMethod.GET)
    area(@RequestParam('parentId') Long parentId) {
    /**
     * 医院列表
     * */
    @RequestMapping(value = "hospital", method = RequestMethod.GET)
    hospital(@RequestParam('areaId') Long areaId) {

t_hospital_basic
    /**
     * 科室列表
     * */
    @RequestMapping(value = "department", method = RequestMethod.GET)
    department(@RequestParam(value = 'hospitalId', required = false) Long hospitalId) {


t_department_basic
t_hospital_ext_department

    /**
     * 医生后台登录
     * @param loginName
     * @param password
     * @return
     */
    @RequestMapping(value = "login", method = RequestMethod.POST)
    login(String loginName, String password) {



1，DoctorBasicService->login(loginName, password)
1.1，通过手机号查询用户信息，t_doctor_basic
1.2，密码加密和查询出来的密码进行对比
1.3，通过查处来的医生ID，或者手机号查询操作信心，把操作信息拼到 DoctorBasic.linkop属性 返回数据
2，获取token


    /**
     * 医生后台注销
     * @return
     */
    @RequestMapping(value = "logout", method = RequestMethod.GET)
    logout(String token, @RequestHeader(value="X-Token", required = false) String headerToken) {
        try {

1，首先通过token获取病人的基本信息
2，TokenCacheUtil.logout（缓存对象，缓存前缀，医生ID）
2.1，获取token之后删除token

    /**
     * 修改 个人密码
     * @param password
     * @param oldPassword
     * @return
     */
    @DoctorConsolePermission(code = "")
    @RequestMapping(value="myPassword", method=RequestMethod.POST)
    editMyPw(String password, String oldPassword, HttpServletRequest request){


1，判断的原始密码
2，修改密码 t_manage_op_basic
3，退出登入

    /**
     * 获取个人信息
     */
    @DoctorConsolePermission(code = "")
    @RequestMapping(value="getInfo", method=RequestMethod.GET)
    getInfo(HttpServletRequest request){

    /**
     * 个人修改 信息
     * @param pk
     * @param value
     * @return
     */
     */
    @DoctorConsolePermission(code = "")
    @RequestMapping(value="editInfo", method=RequestMethod.POST)
    editInfo(String pk,String value, HttpServletRequest request){











    /**
     * 客服后台登录
     * @param loginName
     * @param password
     * @return
     */
    @RequestMapping(value = "login", method = RequestMethod.POST)
    login(String loginName, String password)


    /**
     * 已注册医生列表
     * @return
     */
    @ConsolePermission(code = "console:customerService")
    @RequestMapping(value = "register/list", method = RequestMethod.GET)
    registerList(RequestHelper requestHelper)

    /**
     * 已注册医生详情
     * @return
     */
    @ConsolePermission(code = "console:customerService")
    @RequestMapping(value = "register/{id}", method = RequestMethod.GET)
    registerDetail(@PathVariable("id") Long id)



    /**
     * 医生注册
     * @param callback
     * @param loginName
     * @param password
     * @param userName
     * @param checkCode
     * @return
     */
    @ConsolePermission(code = "console:customerService")
    @RequestMapping(value = "addOpAndDoctor", method = RequestMethod.POST)
    addOpAndDoctor( TDoctorBasic doctorBasic)



    /**
     * 修改医生信息
     * @param doctor
     */
    @ConsolePermission(code = "console:customerService")
    @RequestMapping(value = "register/edit", method = RequestMethod.POST)
    registerEdit( TDoctorBasic doctor)


    }
    /**
     * 修改医生信息
     * @param doctor
     */
    @ConsolePermission(code = "console:customerService")
    @RequestMapping(value = "register/save", method = RequestMethod.POST)
    registerSave(String doctorStr)



    /**
     * 获取方案组集合
     * @param doctorBasic
     */
    protected List<TTemplateGroupBasic> getTemplateGroupList(TDoctorBasic doctorBasic)
        //返回templateGroupList字段，并设置isSelected
        //查询出我的方案组ids
        Map<String, Object> param = [:]



    /**
     * 查询 待审核的医生
     * @param requestHelper
     * @return
     */
    @ConsolePermission(code = "console:customerService")
    @RequestMapping(value = "list/audit", method = RequestMethod.GET)
    listAudit(RequestHelper requestHelper)



    /**
     * 审核 医生
     * @param id
     * @return
     */
    @ConsolePermission(code = "console:customerService")
    @RequestMapping(value = "audit", method = RequestMethod.POST)
    audit(HttpServletRequest request)
        


  /**
   * 退回重新审核 医生
   * @param id
   * @param message
   * @return
   */
  @ConsolePermission(code = "console:customerService")
  @RequestMapping(value = "unAudit", method = RequestMethod.POST)
  unAudit(@RequestParam("id") Long id, @RequestParam("message") String message)
      


    /**
     * 已审核医生列表
     * @return
     */
    @ConsolePermission(code = "console:customerService")
    @RequestMapping(value = "verify/list", method = RequestMethod.GET)
    verifyList(RequestHelper requestHelper)


    /**
     * 已审核医生详情
     * @return
     */
    @ConsolePermission(code = "console:customerService")
    @RequestMapping(value = "verify/{id}", method = RequestMethod.GET)
    verifyDetail(@PathVariable("id") Long id)
		
		
1，发送验证码 手机号，用户类型，验证码类型
2，判断是不是微信用户登入，或者注册，根据 验证码类型
3，查询记录，限制一分钟内只能发送一条短信 t_verification_basic 
4，根据类型调用短信接口发送短信，注册和同步手机号时间为30分中
5，添加一条短信记录  t_verification_basic
		

select id,doctor_ecode, doctor_name, hospital, mobile, email, doctor_desc, sex, department, skill, face, 
    status, id_no, birthday, permit_no, level, create_time, audit_time, audit_op_id, audit_op_real_name, is_active,city,
    position,hospital_id,department_id,new_cust_re,survy_ok_re,new_temp_re, scene_code, qrcode_ticket, weixin_url, last_audit_info_id,
    city_id, city_name,credit_num,recommend_id, my_survey_ok_re,specialty_id,specialty_name,position_id,schedule,app_open_id,position_type,level_end_date,level_start_date,doctor_level 
    from t_doctor_basic where id = 8224;
    
select id, login_name, op_type, password, real_name, email, mobile, doctor_id, status, create_time, 
op_id, op_real_name, is_active from t_manage_op_basic where doctor_id = ? and is_active = 8224;


SELECT a.template_id as id FROM t_template_ext_group a 
WHERE 
EXISTS ( SELECT 1 FROM t_template_group_ext_specialty b WHERE a.template_group_id = b.template_group_id AND (1 = 0 OR (b.specialty_id = ? and b.is_active = 0) ) ) and a.is_active = 0 GROUP BY template_id 

 Preparing: 
 
 
select count(*) from t_msg_basic a where is_active = 0 and ((msg_type like '30%' or (msg_type like '32%' and msg_type != 3200 and create_time > 1471490483000 )
or msg_type = 3200) and (receive_id is null or receive_id = 8224)) and create_time < 1871490483000 and not EXISTS( SELECT * from t_msg_ext_read b where b.target_id = a.id and b.target_type = '0' 
and is_delete = 1 and b.user_type = '2' and b.user_id = 8224 ) 
14:46:28.669 [http-apr-8080-exec-2] DEBUG c.b.i.c.m.T.selectCountByParams - ==> Parameters: 0(String), 1471490483000(Long), 8224(Long), 0(Long), 8224(Long)
		 ReDoPubTemp("提醒医生有新增公共方案", "3205"),

1，通过token查询并且判断是病人还是医生  
2，查询 t_msg_basic 数据，根据医生的注册时间    

    /**
     * 医聊消息查询
     * */
    @RequestMapping(value = "/chart/list", method = RequestMethod.POST)
    chartList(String callback, String token, String type, int page)
          
       chartList
		
        t_msg_ext_read
		
        
            /**
     * Register
     **/
    @RequestMapping(value = "/register", method = RequestMethod.POST)
    register(String callback, String token, String channelId, String osType)
		
		
		            // 先找这个用户的旧数据
            if (channel)
                // 和channel是否相同？
                if (! channelId.equals(channel.channelId))
                    // 不相等？先删除别人在用的这个channelId，在更新
                    params = [:]
                    params << ["channelId": channelId]
                    TPushChannel toDelChannel = pushChannelService.findObj(params) as TPushChannel
                    if (toDelChannel)
                        pushChannelService.delBasic(toDelChannel)
                    }
                    channel.channelId = channelId
                    channel.osType = osType
                    pushChannelService.modifyBasic(channel)
                } else if (!osType.equals(channel.osType))
                    channel.osType = osType
                    pushChannelService.modifyBasic(channel)
                }
            } else {
                // 找不到， 先删除channelId，在插入
                
                1，先找这个用户的旧数据 t_push_channel
                1.1，判断传参数channelid是否和查出来的数据ID相同
                1.2，不相等？先删除别人在用的这个channelId，在更新 t_push_channel
                2， 先删除channelId，在插入   t_push_channel
		
		
		
		
		     /**
     * 发送短信验证码
     * userType 1代表病人，2代表医生
     * codeType 获取校验码的类型（不传代表注册,1代表找回密码，2代表微信登录的校验码,3代表是绑定同步手机号码..目前暂时支持病人段）
     * */
    @RequestMapping(value = "/sendVerification", method = RequestMethod.POST)
    sendVerification(String loginName,
                     @RequestParam(defaultValue = "2") int userType, @RequestParam(defaultValue = "0") int codeType)
        if (loginName == null || loginName == "" || !VerificationUtil.isMobile(loginName) ||
                CommonConstant.UserType.getByType(userType) == null ||
                CommonConstant.CodeType.getByType(codeType) == null)

    @RequestMapping(value = "/sync", method = RequestMethod.POST)
    sync(String appName, Long timestamp, String sign, Long cmsMsgId, String msgTitle, String msgSubTitle, String msgContent, String msgIconUrl, String sysType)

    CMS端消息

    /**
     * 接收消息同步.
     * POST /api/im-msg/receive?timestamp=1408706337&nonce=14314&signature=890b422b75c1c5cb706e4f7921df1d94e69c17f4 HTTP/1.1
     * Host: demo.com.cn
     * fromUserId=123&toUserId=456&objectName=RC%3ATxtMsg&content=%7B"content"%3A"hello"%7D&timestamp=1408710653491&channelType=1&msgTimestamp=1408710653491
     **/
    @RequestMapping(value = "/receive", method = RequestMethod.POST)
    receive(Long timestamp, String nonce, String signature,
            String fromUserId, String toUserId, String objectName, String content, Integer channelType, Long msgTimestamp)
        



    /**
     * 系统消息查询
     **/
    @RequestMapping(value = "/system/list", method = RequestMethod.POST)
    systemList(String callback, String token, String type, Long lastUpdateDate, int page, String keywords)


    /**
     * 系统消息修改targetId
     **/
    @RequestMapping(value = "/editTargetId", method = RequestMethod.POST)


    /**
     * 更新消息阅读状态
     * */
    @RequestMapping(value = "/editStatus", method = RequestMethod.POST)
    editStatus(String callback, String token, String msgId, String status)
        

        /**
     * 添加已阅读信息到t_rxt_read表
     * @param callback
     * @param type 0:系统消息 1:须知 2:量表 3:医数发布 4:医数空间
     * @param id :linkPointId,msgId
     * @param token
     * @return
     */
    @RequestMapping(value = "/addReadRecord")
    insertMsgRead(String callback, String type, String id, String token,Long subId)
        

    /**
     * update 消息的 isDelete 状态
     * @param callback
     * @param type 0:系统消息 1:须知 2:量表 3:医数发布 4:医数空间
     * @param targetId :linkPointId,msgId
     * @param token
     * @return
     */
    @RequestMapping(value = "/delete", method = RequestMethod.POST)
    delete(String callback, String type, Long targetId, String token)

deleteAll(String callback, String type, String token)


    /**
     * 批量添加已阅读信息到t_rxt_read表
     * @param callback
     * @param type 0:系统消息 3:医数发布
     * @param id :linkPointId,msgId
     * @param token
     * @return
     */
    @RequestMapping(value = "/setAllMsgReaded")
    setAllMsgReaded(String callback, String token, String type)

    /**
     * 获取自己的未读消息数
     * @param token
     * @param userType
     */
    @RequestMapping(value = "/getUnreadMsgCount", method = RequestMethod.POST)
    getUnreadMsgCount(String callback, String token, String userType)

        /**
     * 消息详情
     */
    @RequestMapping(value = "/detail", method = RequestMethod.POST)
    detail(String callback, String token, Long msgId)

    PushChannelApi
        /**
     * Register
     **/
    @RequestMapping(value = "/register", method = RequestMethod.POST)
    register(String callback, String token, String channelId, String osType)
        log.debug("------------liuaiguo-------------------------------- token {},channelId {},osType {}",token,channelId,osType)
        
		
		    /**
     * 患教库列表
     * @param
     * @return
     */
    @DoctorConsolePermission(code = "material:view")
    @RequestMapping(value = "list", method = RequestMethod.GET)
    list(@RequestParam(value = "subjects", required = false) String subjectStr,
         @RequestParam(value = "tags", required = false) String tags,
         @RequestParam(value = "keyword", required = false) String keyword,
         @RequestParam(value = "page", required = false) Integer page) {
		
		
		    /**
     * 我的患教列表
     * @param
     * @return
     */
    @DoctorConsolePermission(code = "material:view")
    @RequestMapping(value = "myList", method = RequestMethod.GET)
    myList(@RequestParam(value = "tags", required = false) String tags,
           @RequestParam(value = "keyword", required = false) String keyword,
           @RequestParam(value = "page", required = false) Integer page,
           @RequestParam(value = "pageSize", required = false) Integer pageSize,
           HttpServletRequest request) {
		

    from t_doctor_material_relation dmr join t_material_basic m on dmr.material_id = m.id

    /** t_doctor_material_relation
     * 我的患教ID列表
     * @param
     * @return
     */
    @DoctorConsolePermission(code = "material:view")
    @RequestMapping(value = "myListIds", method = RequestMethod.GET)
    myListIds(
           HttpServletRequest request) {

    }

    /**
     * 新增患教
     * @param
     * @return
     */
    @DoctorConsolePermission(code = "material:edit")
    @RequestMapping(value = "add", method = RequestMethod.POST)
    add(@RequestBody TMaterialBasic materialBasic, HttpServletRequest request) {

          /**
     * 修改患教
     * @param
     * @return
     */
    @DoctorConsolePermission(code = "material:edit")
    @RequestMapping(value = "edit", method = RequestMethod.POST)
    edit(@RequestBody TMaterialBasic materialBasic, HttpServletRequest request) {





    /**
     * 启用停用患教
     * @param
     * @return
     */
    @DoctorConsolePermission(code = "material:edit")
    @RequestMapping(value = "setStatus", method = RequestMethod.POST)
    setStatus(@RequestBody TMaterialBasic materialBasic, HttpServletRequest request) {
1，更新status   t_material_basic
2，如果状态为开启状态需要同步 DoctorMaterialRelationService->syncDoctorMaterialRelation(TMaterialBasic material)
2.1，


    /**
     * 绑定方案
     * @param
     * @return
     */
    @DoctorConsolePermission(code = "material:edit")
    @RequestMapping(value = "bind", method = RequestMethod.POST)
    bind(Long materialId, Long followTemplateId, HttpServletRequest request) {
      /**
     * 解绑方案
     * @param
     * @return
     */
    @DoctorConsolePermission(code = "material:edit")
    @RequestMapping(value = "unbind", method = RequestMethod.POST)
    unbind(@RequestBody TMaterialBasic materialBasic, HttpServletRequest request) {

      /**
     * 加为我的患教
     * @param
     * @return
     */
    @DoctorConsolePermission(code = "material:view")
    @RequestMapping(value = "{id}/addToMyList", method = RequestMethod.POST)
    addToMyList(@PathVariable(value = "id") Long id,
                HttpServletRequest request) {
      DoctorMaterialRelationService->addToMyList(教患详情, 医生详情)

1，通过ID查询数据存不存在 t_material_basic
2，获取医生的数据通过 request
3，DoctorMaterialRelationService->addToMyList(教患详情, 医生详情)
3.1，查询医生教患关联表有没有相同的数据，有直接return  t_doctor_material_relation
3.2，没有数据直接添加数据 t_doctor_material_relation

    /**
     * 启用停用我的患教
     * @param
     * @return
     */
    @DoctorConsolePermission(code = "material:view")
    @RequestMapping(value = "setStatusInMyList", method = RequestMethod.POST)
    setStatusInMyList(@RequestBody TDoctorMaterialRelation doctorMaterialRelation, HttpServletRequest request) {
1，通过教患关联ID获取教患关联数据 t_doctor_material_relation
2，获取医生基本信息 通过 request
3，更新教患关联表状态 t_doctor_material_relation 


    /**
     * 列出专区
     * @param
     * @return
     */
    @DoctorConsolePermission(code = "materialTag:view")
    @RequestMapping(value = "list", method = RequestMethod.GET)
    list() {

      t_material_subject

      /**
     * 列出所有的tag
     * @param
     * @return
     */
    @DoctorConsolePermission(code="materialTag:view")
    @RequestMapping(value = "list", method = RequestMethod.GET)
    list(@RequestParam(value = "tagGroupId", required = false) Long tagGroupId,
            @RequestParam(value = "type", required = false) Integer type) {

        Map<String, Object> param = [:]

    /**
     * 增加标签
     * @param
     * @return
     */
    @DoctorConsolePermission(code = "materialTag:edit")
    @RequestMapping(value = "add", method = RequestMethod.POST)
    add(@RequestBody TMaterialTag materialTag) {

        TMaterialTag obj = new TMaterialTag()
        obj.title = TagUtil.trim(materialTag.title)
        obj.type = 0
        obj.tagGroup = materialTag.tagGroup
        obj.orderBy = 0
        obj.count = 0

        if (!obj.title) return new ResultHelper(resCode: 'A004')

        Map<String, Object> param = [:]
        param['title'] = obj.title

        if (materialTagService.findCountByParams(param) > 0)
            return new ResultHelper(resCode: '4402')

        param = [:]
        param['tagGroup'] = obj.tagGroup
        obj.orderBy = materialTagService.findCountByParams(param) + 1

        materialTagService.addBasic(obj)
        return [resCode: ResCodeMessageCache.Success, model: obj]
    }


    /**
     * 移除标签（移除的标签不会被删除,会在游离状态）
     * @param
     * @return
     */
    @DoctorConsolePermission(code = "materialTag:edit")
    @RequestMapping(value = "remove", method = RequestMethod.POST)
    remove(@RequestBody TMaterialTag materialTag) {
          /**
     * 列出标签组
     * @param
     * @return
     */
    @DoctorConsolePermission(code = "materialTag:view")
    @RequestMapping(value = "list", method = RequestMethod.GET)
    list(@RequestParam(value = "type", required = false) Integer type,
         @RequestParam(value = "types", required = false) String types) {


    /**
     * 增加标签组
     * @param
     * @return
     */
    @DoctorConsolePermission(code = "materialTag:edit")
    @RequestMapping(value = "add", method = RequestMethod.POST)
    add(@RequestBody TMaterialTagGroup materialTagGroup) {

      t_material_tag_group
          @DoctorConsolePermission(code = "material:edit")
    @RequestMapping(value = "list", method = RequestMethod.GET)
    list(@RequestParam(value = "keyword") String keyword,
         @RequestParam(value = "page", required = false) Integer page,
         HttpServletRequest request) {

      t_notes_basic


          @DoctorConsolePermission(code = "material:view")
    @RequestMapping(value = "list", method = RequestMethod.GET)
    list(@RequestParam(value = "op", required = false) Long opId) {


1，获取模板列表 type in (0,2,3,4 ) t_follow_template

    /**
     * 返回 节点 列表
     * 返回 系统节点和 自定义节点
     * @return
     */
    @DoctorConsolePermission(code="material:view")
    @RequestMapping(value="list", method=RequestMethod.GET)
    allList(HttpServletRequest request) {

      t_follow_template_point

          /**
     * 随访方案 节点关联 修改
     * @param followTemplate
     */
    @DoctorConsolePermission(code = "material:edit")
    @RequestMapping(value="edit", method=RequestMethod.POST)
    edit(@RequestBody TFollowTemplate followTemplate, HttpServletRequest request){
        try {templateService.modifyLink(followTemplate, op)
1，首先拼好须知管理表的数据
2，查询方案记录 t_follow_template
3，获取操作表记录  通过 request
4，调用修改方法 templateService.modifyLink(followTemplate, op)
4.1，修改所有的记录变成无效  TFollowPointLinkMapper.setIsActiveByTemplateId(模板ID, isactive=1)
4.2， 当link的方案id,link类型,linkId都一致,没有发生变更的时候,直接修改link,保持link.id不变; 否则按照新的link数据进行插入,用有新的link.id
5，删除方案简介的缓存
   TemplateDescriptionDetailCacheUitl.deleteDetail(cacheTemplate, followTemplate.id)


        /**
         * 获取活动详情
         */
        @RequestMapping(value = "detail", method = RequestMethod.POST)
        @APIPermission(type = 1)
        detail(Long activityId) {
            if (!activityId) {
                return JSONReturnUtils.fail("400")
            }
1，活动ID必传
2，通过ID查找记录 t_liveplay_activity_basic
3，创建二维码 LivePlayActivityBasicService->fillActivityQcCodeScene(activityBasic)
3.1，创建二维码 wxMpService.qrCodeCreateTmpTicket(sceneId, expiredSeconds)
3.2，缓存时间为29天 返回数据
4，更新数据，更新微信url，微信url时间

EntryFromApi

    /**
     * 获取报名详情
     */
    @RequestMapping(value = "detail", method = RequestMethod.POST)
    @APIPermission(type = 1,platformTokenKey = CommonConstant.PlatformTokenKey.MedicalSpeechCustomer)
    detail(Long activityId) {

1，如果不穿ID默认取第一条数据
2，通过ID查询数据 t_liveplay_activity_basic
3，如果上一步已过期数据，在查询一条有效的数据 t_liveplay_activity_basic
4，判断活动的报名时间
5，获取报名表的信息 t_liveplay_entryfrom_basic 没记录说明没报名

    /**
     * 提交报名详情
     */
    @RequestMapping(value = "confirm", method = RequestMethod.POST)
    @APIPermission(type = 1,platformTokenKey = CommonConstant.PlatformTokenKey.MedicalSpeechCustomer)
    confirm(String name, String mobile, Integer sex, String areaTitle, Long areaId, Long activityId) {
1，通过拦截器获取病人的记录
2，通过活动ID，获取活动记录 t_liveplay_activity_basic
3，如果活动已过期的话查询一条有效活动的数据 t_liveplay_activity_basic
4，如果病人的手机号，为空把传进来的手机号赋值到病人记录的手机号
5，如果名字为空的话，把传过来的名字赋值到病人的名字里面
6，如果第四第五成立更新病人数据 t_customer_basic
7，查询是否已提交报名，已报名直接return  t_liveplay_entryfrom_basic
8，没有提交报名新增一条报名数据   t_liveplay_entryfrom_basic
9，把报名数据重新查出来（这人有病）
10，给用户发一个微信消息  （微信消息）
11，获取医生的基本信息 t_doctor_basic 通过上一步查询的医生ID
12，临时把病历的名字赋值报名的名字
13，查询病例记录，没有的话创建一条记录 t_customer_ext_hospital


微信模版消息
  
  医术值列表

  logList(Integer page) {
     select id, FROM_UNIXTIME(( `create_time`/1000),'%Y-%m-%d %H:%i:%s') AS create_time , credit, is_active, user_id, `desc`, target_id, `type`,reward_num,reward_status from t_credit_log where user_id=? and is_active=? order by create_time desc limit ? , ? 
    @RequestMapping(value = "getMyRecommendedList", method = RequestMethod.POST)
    getMyRecommendedList(String token, String callback, int page) {  


          /**
     * 查询 病人 列表
     * @param callback
     * @param token
     * @param page
     * @param status
     * @return
     */
    @RequestMapping(value = "list", method = RequestMethod.POST)
    @APIPermission
    list(String status, String customerName, HttpServletRequest request) {

      api/doctor/customer

      http://localhost:8080/api/doctor/customer/list?token=&status=&customerName=

select id,doctor_ecode, doctor_name, hospital, mobile, email, doctor_desc, sex, department, skill, face, status, id_no, birthday, permit_no, level, create_time, audit_time, audit_op_id, audit_op_real_name, is_active,city,position,hospital_id,department_id,new_cust_re,survy_ok_re,new_temp_re, scene_code, qrcode_ticket, weixin_url, last_audit_info_id, city_id, city_name,credit_num,recommend_id, my_survey_ok_re,specialty_id,specialty_name,position_id,schedule,app_open_id,position_type,level_end_date,level_start_date,doctor_level
from 
t_doctor_basic where id = 8224 

 select id, login_name, op_type, password, real_name, email, mobile, doctor_id, 
 status, create_time, op_id, op_real_name, is_active 
 from t_manage_op_basic 
 where doctor_id = 8224 and is_active = 0

  select 
      tceh.id, tceh.customer_id, tceh.hospital, tceh.bed_no, 
      tceh.customer_code, tceh.customer_desc, tceh.template_id, tceh.firstPointStartTime,
      tcb.mobile, tceh.template_name, tceh.status, tceh.create_time, 
      tceh.doctor_id, tceh.doctor_name, tceh.is_active, tceh.im_blocked_at, tceh.remark, 
      tceh.up_time, tceh.mark,tceh.customer_alias,tceh.customerDescContent,
      tceh.in_progress_point_time , tcb.real_name as customer_name, 
      tcb.sex,tcb.age,tcb.face,tcb.rc_token,tcb.birthday,

      (select count(1)
        from t_media_relation tmr 
        where tmr.target_id=tceh.id and tmr.target_type='2' and tmr.is_active='0'
      ) as remarkNum
  from 
      t_customer_ext_hospital tceh 
  JOIN 
      t_customer_basic tcb on tceh.customer_id=tcb.id and tcb.is_active = 0 
  where 
      tceh.customer_name like "%"QA014"%" and 
      tceh.status in ('-1','0') and 
      tceh.doctor_id = 8224 and 
      tceh.is_active = 0 and 
      ((tceh.status= -1 and tceh.create_time >1472745600000) or tceh.status=0) and 
      tceh.is_active=0 and 
      tceh.status !='9' order by CREATE_TIME desc;


          /**
     * 查询 客户详情
     * @param callback
     * @param token
     * @param customerId
     * @return
     */
    @RequestMapping(value = "{customerId}", method = RequestMethod.POST)
    detail(String callback, String token, Long time, String type,
           @PathVariable("customerId") Long customerId, HttpServletRequest request, Long customerExtHosp) {

findCustomerExtHospitalByType(TDoctorBasic doctorBasic, TCustomerBasic customerBasic, Long customerId, Long time,
                                                               String type)
1，通过token查找医生记录    t_doctor_basic
2，通过customerID朝朝病人记录 t_customer_basic
3，判断是不是微信医生，版本号，手机类型
3.1，查询随访记录状态为（待分配，已分配的数据） t_customer_ext_hospital
3.2，findCustomerExtHospitalByType(医生基本信息, 患者基本信息,患者ID, 创建时间,随访状态)
4， findCustomerExtHospitalByTypeNew(医生基本信息, 患者基本信息, 患者ID, 创建时间, 随访状态, 随访ID)
4.1，查询所有的随访记录 t_customer_ext_hospital
4.2，如果传ID，通过ID查询随访记录，如果没穿ID通过其他条件查询随访记录一条 t_customer_ext_hospital
4.3，通过4.1记录循环查出来的模板ID查询模板记录拼在详情记录里 t_follow_template

03b3f5c69caf4dc7a971f34ffea823e9

    /**
     * 分组 确认
     * @param callback
     * @param token
     * @param customerId
     * @param customerName
     * @param templateId
     * @param customerDesc
     * @param templateName
     */
    @RequestMapping(value = "confirm", method = RequestMethod.POST)
    confirmCustomer(String callback, String token, Long customerId, String customerName, Long templateId, String customerDesc, String templateName,
                    Long oldTemplateId, Long pointId, String firstPointStartTime) {


customerId 22098